Commit 8c2c4827 authored by mark@mpc1685's avatar mark@mpc1685
Browse files

Added a libuv based picoserverli which allows access to the picoscope from...

Added a libuv based picoserverli which allows access to the picoscope from multiple clients properly
parent ffaa887e
......@@ -5,6 +5,11 @@
# Mark Koennecke, May 2015
#--------------------------------------------------------------
all: picocontrol picoserverli
picoserverli: picoserverli.o
gcc -g -o picoserverli picoserverli.o -L/opt/picoscope/lib -lps2000a -luv
picocontrol: picocontrol.o
gcc -g -o picocontrol picocontrol.o -L/opt/picoscope/lib -lps2000a
......
......@@ -28,7 +28,7 @@ static void StopPico(void)
{
ps2000aCloseUnit(handle);
}
/*--------------------------------------------------------------*/
/*--------------------------------------------------------------*/
static void SetGenerator(long freq, float ampl)
{
int status;
......
/*
This is a little server for controling the frequencz generator built into
the picoscope oscilloscope.
It turned out that picocontrol is not sufficient: it is run by xinetd
and does not properly recognized disconnects. Which in turn did not
close picoconetrol and then the port ot the picoscope was blocked.
This is now a little libUV based server which allows multiple clients
to connect to the picoscope and managing the connection to the picoscope.
This is an event based server, thus serialisation of access to the picoscope
is being taken care of by design.
Mark Koennecke, September 2017
*/
#include <sys/types.h>
#include <string.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <libps2000a-1.1/ps2000aApi.h>
#ifndef PICO_STATUS
#include <libps2000a-1.1/PicoStatus.h>
#endif
#include <uv.h>
static short handle;
/*===============================================================
Defaults
=================================================================*/
#define PORT 3030
#define FREQ 1000
#define AMPL 0.0
#define MULT 1000000
#include <sys/types.h>
#include <string.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <libps2000a-1.1/ps2000aApi.h>
#ifndef PICO_STATUS
#include <libps2000a-1.1/PicoStatus.h>
#endif
/*================= Ugly but easy globals ======================*/
static short handle;
static unsigned int glFreq = FREQ;
static double glAmpl = .0;
/*--------------------------------------------------------------*/
static void StopPico(void)
{
ps2000aCloseUnit(handle);
}
/*--------------------------------------------------------------*/
static void SetGenerator(long freq, float ampl)
{
int status;
if(freq == 0){
status = ps2000aSetSigGenBuiltIn(handle,
0,
0,
PS2000A_DC_VOLTAGE,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0);
} else {
status = ps2000aSetSigGenBuiltIn(handle,
0,
(unsigned long)ampl,
PS2000A_SINE,
(float)freq,
(float)freq,
0,
0,
0,
0,
0,
0,
0,
0,
0);
}
if(status != PICO_OK){
printf("Failed to configure signal generator with %d\n", status);
}
}
/*---------------------------------------------------------------------*/
void picoBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
{
size_t pSize;
if(suggested_size > 8192){
pSize = suggested_size;
} else {
pSize = 8192;
}
*buf = uv_buf_init(malloc(pSize),pSize);
}
/*--------------------------------------------------------------------*/
static void picoWriteCallback(uv_write_t *req, int status)
{
free(req);
}
/*---------------------------------------------------------------------*/
static void picoSendReply(uv_stream_t *stream, char *reply)
{
uv_write_t *wreq;
uv_buf_t buf;
wreq = malloc(sizeof(uv_write_t));
buf = uv_buf_init(malloc(strlen(reply)+1),strlen(reply)+1);
strcpy(buf.base,reply);
uv_write((uv_write_t*)wreq,stream,&buf,1,picoWriteCallback);
}
/*----------------------------------------------------------------------*/
void picoRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
{
char *command, *pPtr, token[50], reply[80];
int status;
float tmp;
int freq;
if(nread < 0){
if(nread == UV_EOF){
uv_close((uv_handle_t*)stream, NULL);
printf("Closing stream\n");
}
} else {
printf("Processing command %s\n",buf->base);
/*
Here we are now in business: our action code!!!
*/
command = buf->base;
pPtr = strchr(command,'\n');
*pPtr = '\0';
if(strstr(command,"freq") != NULL){
status = sscanf(command,"%s %d",token, &freq);
if(status == 2){
glFreq = freq;
SetGenerator(glFreq,glAmpl*MULT);
strcpy(reply,"OK\n");
} else {
snprintf(reply,sizeof(reply),"freq %d\n",glFreq);
}
picoSendReply(stream,reply);
} else if(strstr(command,"ampl") != NULL){
status = sscanf(command,"%s %f",token, &tmp);
if(status == 2){
glAmpl = tmp;
SetGenerator(glFreq,glAmpl*MULT);
strcpy(reply,"OK\n");
} else {
snprintf(reply,sizeof(reply),"ampl %f\n",glAmpl);
}
picoSendReply(stream,reply);
} else {
snprintf(reply,sizeof(reply),"Command %s not understood. use freq, ampl\n", command);
picoSendReply(stream,reply);
}
free(buf->base);
}
}
/*----------------------------------------------------------------------*/
static void picoNewConnection(uv_stream_t *server, int status)
{
uv_tcp_t *client;
if(status < 0) {
printf("New connection error %s\n", uv_strerror(status));
return;
}
client = malloc(sizeof(uv_tcp_t));
uv_tcp_init((uv_loop_t*)server->data,client);
if(uv_accept(server,(uv_stream_t*)client) == 0){
uv_read_start((uv_stream_t*)client,picoBuffer,picoRead);
}
}
/*========================================================================*/
int main(int argc, char *argv[])
{
int status;
long int freq = 1000;
float mult = 1000000, ampl = 1.*mult, tmp;
char line[80], token[80];
uv_loop_t *loop;
uv_tcp_t server;
struct sockaddr_in addr;
status = ps2000aOpenUnit(&handle, NULL);
if(status != PICO_OK){
printf("Failed to open picoscope with %d\n", status);
exit(1);
}
atexit(StopPico);
loop = malloc(sizeof(uv_loop_t));
if(loop == NULL){
printf("Out of memory allocating UV data structure \n");
exit(1);
}
uv_loop_init(loop);
/*
setup of a server port
*/
uv_tcp_init(loop,&server);
uv_ip4_addr("0.0.0.0",PORT,&addr);
uv_tcp_bind(&server,(const struct sockaddr *)&addr,0);
status = uv_listen((uv_stream_t*)&server, 5,picoNewConnection);
if(status){
printf("Listen error %s\n", uv_strerror(status));
exit(1);
}
server.data = loop;
uv_run(loop,UV_RUN_DEFAULT);
uv_loop_close(loop);
free(loop);
StopPico();
exit(0);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment