arduino.cpp 5.27 KB
//
//  Created by Arnaud Blanchard on 22/12/15.
//  Copyright ETIS 2015. All rights reserved.
//

#include "serial.h"
#include "blc_program.h"
#include "blc_channel.h"


#include <errno.h> //errno
#include <sys/uio.h> //writev
#include <unistd.h>


#define PINS_MAX 256

char  const *display;
char  const  *device_name;


void display_cb(char const*, void*){
    if (display) {
        blc_eprint_del_end_screen();
        display=NULL;
    }else   display="1";
}



void on_quit(){
    if (display) blc_eprint_del_end_screen();
}

int main(int argc, char **argv){
    blc_channel channel;
    char buff[256];
    char const *message;
    blc_mem sending_mem, receiving_mem;
    char const *analog, *filename_str, *channel_name, *servos;
    int   pos, tmp_pos;
    char ready, answer_size;
    int display_height=16;
    char const  *baudrate_str;
    int  fd, i;
    uchar pins_ids[PINS_MAX];
    uint16_t *pins_values;
    int pins_nb, tmp_pin_id, rv;
    FILE *record_file=NULL;
    struct timeval timeout;
    fd_set set;
    int received_bytes_nb, baudrate;
    int timeout_seconds=3;
    
    struct sending_header{
        char command;
        uchar pins_nb;
    }*sending_header;
    
    struct receiving_header{
        char answer;
        uchar pins_nb;
    }*receiving_header;
    
    blc_program_add_option(&analog, 'a', "analog", "integer list",  "list of analog port to read", NULL);
    blc_program_add_option(&baudrate_str, 'b', "baudrate", "integer",  "serial port speed", "115200");
    blc_program_add_option(&display, 'd', "display", NULL,  "display graph and values", NULL);
    blc_program_add_option(&servos, 's', "servos", "string",  "pins to drive servo motors \"pin1 pin2 pin3 ...\"", NULL);
    blc_program_add_parameter(&device_name, "device", 0, "device name", "/dev/ttyUSB0");
    blc_program_init(&argc, &argv, on_quit);
    
    baudrate=strtol(baudrate_str, NULL, 10);
    
    if (analog){
        pos=0;
        pins_nb=0;
        
        while (sscanf(analog+pos, "%d%n", &tmp_pin_id, &tmp_pos)==1){
            if (pins_nb == PINS_MAX) EXIT_ON_ERROR("Too many pins (max %d)", PINS_MAX);
            pins_ids[pins_nb]=tmp_pin_id; //Necessary to convert int to uchar
            pos+=tmp_pos;
            pins_nb++;
        }
        
        //We allocate the header and the list of pins to read
        sending_mem.allocate(sizeof(struct sending_header));
        sending_mem.append((char*)pins_ids, pins_nb*sizeof(uchar));
        
        //We assign the first part of the memory to the header
        sending_header=(struct sending_header*)sending_mem.data;
        sending_header->command='a';
        sending_header->pins_nb=pins_nb;
        
        receiving_mem.allocate(sizeof(struct receiving_header)+pins_nb*sizeof(uint16_t));
        receiving_header=(struct receiving_header*)receiving_mem.data;
        pins_values=(uint16_t*)(receiving_mem.chars+sizeof(struct receiving_header));
        
        channel_name="/toto";
        channel.create_or_open(channel_name, BLC_CHANNEL_WRITE, 'UIN8', 'NDEF', 1, pins_nb);
        channel.publish();
    }
    
    
    fd = open_serial_port(device_name, baudrate, 8, 'N', 2);
    eprint_serial_port_options(fd);
    
    FD_ZERO(&set); /* clear the set */
    FD_SET(fd, &set); /* add our file descriptor to the set */
    
    timeout.tv_sec = timeout_seconds;
    timeout.tv_usec = 0;
    
    
    rv = select(fd + 1, &set, NULL, NULL, &timeout);
    
    if (rv==0) EXIT_ON_ERROR("Timeout after %ds waiting arduino answer to message:\n'%s'\non '%s'.", timeout_seconds,  message, device_name);
    else if (rv==-1) EXIT_ON_ERROR("Error\n");
    
    BLC_COMMAND_LOOP(100000){
        
        serial_send_buffer(fd, sending_mem.chars, sending_mem.size);
        //qreceived_bytes_nb=read(fd, receiving_mem.chars, receiving_mem.size);
        
        received_bytes_nb=serial_receive_buffer(fd, receiving_mem.chars, receiving_mem.size, 3000);
        
        if (received_bytes_nb>0){
            
            if (receiving_header->answer != sending_header->command) {
                switch  (receiving_header->answer){
                    case 'e':fprintf(stderr, "error %d\n", receiving_header->pins_nb);
                        break;
                    case 'r':fprintf(stderr, "The board has been restarted\n");
                        break;
                    default:fprintf(stderr, "receiving answer size '%d': '%c' instead of '%c'\n", received_bytes_nb, receiving_header->answer, sending_header->command);
                }
                //         tcflush(fd, TCIOFLUSH);
            }else{
                FOR(i, pins_nb) channel.uchars[i]=pins_values[i]/4;
                
                if (display){
                    blc_eprint_del_end_screen();
                    channel.fprint_graph_uchars(stderr, "arduino", display_height,  256, 0, "pins ", "volt ");
                    fprintf(stderr,"values:");
                    FOR(i, pins_nb) fprintf(stderr, "%d ", pins_values[i]);
                    
                    blc_eprint_cursor_up(display_height);
                }else write(STDERR_FILENO, ".", 1);
                
                if (record_file){
                    FOR(i, pins_nb) fprintf(record_file, "%d ", pins_values[i]);
                    fprintf(record_file, "\n");
                }
            }
        }
    }
    
    return EXIT_SUCCESS;
}