2014-12-10 5:41 1 second pulse (serial)

Dependencies:   MODSERIALhacked Convert SLCD mbed-src

main.cpp

Committer:
jhaugen
Date:
2014-12-18
Revision:
12:c97d6cd17314
Parent:
11:79eabc671800

File content as of revision 12:c97d6cd17314:

#include "mbed.h"
#include "convert.h"
#include "double_buffer.h"

#include "MODSERIAL.h"

#include "sine_table.h"

#define SINE_OUT_FREQ_MASK 3
#define SINE_OUT_FREQ_1HZ 0
#define SINE_OUT_FREQ_10HZ 1
#define SINE_OUT_FREQ_100HZ 2
#define SINE_OUT_FREQ_1000HZ 3

#define SINE_OUT_ON_MASK 4
#define SINE_OUT_ON 4
#define SINE_OUT_OFF 0

#define D_OUT_MASK 8
#define D_OUT_ON 8
#define D_OUT_OFF 0

#define ADC_SAMP_FREQ_MASK 48
#define ADC_SAMP_FREQ_OFF 0
#define ADC_SAMP_FREQ_1HZ 16
#define ADC_SAMP_FREQ_10HZ 32
#define ADC_SAMP_FREQ_100HZ 48

#define SINE_TABLE_SIZE 1000

MODSERIAL pc(USBTX, USBRX);

AnalogIn my_light_sensor(PTE22);
AnalogIn my_analog_pin(PTB0);

AnalogOut sine_out_pin(PTE30);

InterruptIn d_event_pin(PTA4);

// false == on; true == off for the leds
DigitalOut myled(LED_GREEN);
DigitalOut redled(LED_RED);
DigitalOut hundms_pulse_pin(PTA12);
DigitalOut d_out_pin(PTD3);
Timer timer;
long long offset = 0;

DoubleBuffer<unsigned short, 50> light_sensor_buffer;
DoubleBuffer<unsigned short, 500> adc_buffer;
DoubleBuffer<long long, 30> d_event_buffer;

//initialize variables
Ticker ticker;
char t1_string[31];
char t4_string[31];
int t2;
int t3;
//int i = 0;
bool pulse_value = false;
//float let_there_be_light = 0.0;
//float my_analog_value = 0.0;
Convert lcd;

//int adc_sampling_on = 0;
int d_out_on = 0;
int sine_out_on = 0;

int adc_sampling_frequency = ADC_SAMP_FREQ_1HZ;
int sine_out_frequency = SINE_OUT_FREQ_1000HZ;

#define ANALOG_VALUE_BUFFER_SIZE 500

/*float analog_values[2][ANALOG_VALUE_BUFFER_SIZE];
int analog_fill_buffer = 0;
int analog_value0_size = 0;
int analog_value1_size = 0;*/

//bool read_complete = false;

int tick_count = 0;
int sine_index = 0;


// sets the flags from the website backend
void set_options(char opt) {
    adc_sampling_frequency = opt & ADC_SAMP_FREQ_MASK;
    d_out_on = opt & D_OUT_MASK;
    sine_out_on = opt & SINE_OUT_ON_MASK;
    sine_out_frequency = opt & SINE_OUT_FREQ_MASK;
}

/*void read_adc() {
    int analog_buffer_size;
    if (analog_fill_buffer == 0) {
        if (analog_value0_size >= ANALOG_VALUE_BUFFER_SIZE) {
            return;
        }
        analog_buffer_size = analog_value0_size;
        analog_value0_size++;
    }
    else {
        if (analog_value1_size >= ANALOG_VALUE_BUFFER_SIZE) {
            return;
        }
        analog_buffer_size = analog_value1_size;
        analog_value1_size++;
    }
    analog_values[analog_fill_buffer][analog_buffer_size] = my_analog_pin.read();
}*/

/*
void send_adc_data() {
    int send_buffer = analog_fill_buffer;
    int send_buffer_size;
    // switch the fill buffer
    if (analog_fill_buffer == 0) {
        // make sure the new buffer is empty
        analog_value1_size = 0;
        analog_fill_buffer = 1;
        send_buffer_size = analog_value0_size;
    }
    else {
        // make sure the new buffer is empty
        analog_value0_size = 0;
        analog_fill_buffer = 0;
        send_buffer_size = analog_value1_size;
    }
    
    // send the header: the letter 'a' followed by the number of 32-bit floating point numbers
    pc.putc('a');
    pc.putc(send_buffer_size);
    
    // send the data in the old buffer
    for(int i = 0; i < send_buffer_size; i++) {
        pc.putc(analog_values[send_buffer][i]);
    }
}*/

// sends unsigned long long in big endian (msb first)
void send_ull(long long l) {
    char* l_array = (char*)&l;
    for (int i = 7; i >= 0; i--) {
        pc.putc(l_array[i]);
    }
}

void send_int(int integer) {
    char* i_array = (char*)&integer;
    for (int i = 3; i >= 0; i--) {
        pc.putc(i_array[i]);
    }
}

void send_us(unsigned short us) {
    char* us_array = (char*)&us;
    pc.putc(us_array[1]);
    pc.putc(us_array[0]);
}

long long last_systick_second = 0;
int systick_high_count = 0;

void systick() {
    long long curr_systick_second = (((long long) timer.read_us()) - offset) / 1000000;
    
    if (curr_systick_second > last_systick_second) {
        myled = false;
        hundms_pulse_pin = true;
        last_systick_second = curr_systick_second;
        systick_high_count = tick_count;
    }
    else if (tick_count == systick_high_count + 1000) {
        myled = true;
        hundms_pulse_pin = false;
    }
    //if (tick_count % 20000 == 0) {
    if (tick_count % 10000 == 0) {
        //redled = false;
        // set the pulse high for 100ms, .1 s        
        // toggle a led
        //pulse_value = false;
        //myled = pulse_value;
        //hundms_pulse_pin = true;
        
        // get data from the (2) light sensor (3) analog pin
        //let_there_be_light = my_light_sensor.read();
        unsigned short light_val = my_light_sensor.read_u16();
        light_sensor_buffer.write(light_val, ((long long) timer.read_us()) - offset);
        //my_analog_value = my_analog_pin.read();
            
        // print the analog values to uart
        //pc.printf("%f,%f\r\n", let_there_be_light, my_analog_value);
        
        // display 1
        //lcd.display(1);
                //wait_ms(100.0f);
    }
    //else if (tick_count % 20000 == 2000) {
    else if (tick_count % 10000 == 1000) {
        //redled = true;
        // set the pulse low for 900 ms, .9 s
        // toggle a led
        //pulse_value = true;
       // myled = pulse_value; // toggle a led
       // hundms_pulse_pin = false;
        
        // get data from the (2) light sensor (3) analog pin
        //let_there_be_light = my_light_sensor.read();
        //my_analog_value = my_analog_pin.read();
        
        // print the analog values to uart
        //pc.printf("%f,%f\r\n", let_there_be_light, my_analog_value);
        
        // display 0
        //lcd.display(0);
                //wait_ms(900.0f);
    }
    
    if (sine_out_on == SINE_OUT_ON) {
        sine_out_pin.write_u16(sine_table[sine_index]);
        
        switch (sine_out_frequency) {
            case SINE_OUT_FREQ_1HZ:
                // every 10 ticks, increment sine_index
                if (tick_count % 10 == 0) {
                    sine_index += 1;
                }
                break;
            case SINE_OUT_FREQ_10HZ:
                sine_index += 1;
                break;
            case SINE_OUT_FREQ_100HZ:
                sine_index += 10;
                break;
            case SINE_OUT_FREQ_1000HZ:
                sine_index += 100;
                break;
        }
        
        // uncomment this for 50 us period
        /*switch (sine_out_frequency) {
            case SINE_OUT_FREQ_1HZ:
                // every 10 ticks, increment sine_index
                if (tick_count % 20 == 0) {
                    sine_index += 1;
                }
                break;
            case SINE_OUT_FREQ_10HZ:
                if (tick_count % 2 == 0) {
                    sine_index += 1;
                }
                break;
            case SINE_OUT_FREQ_100HZ:
                sine_index += 5;
                break;
            case SINE_OUT_FREQ_1000HZ:
                sine_index += 50;
                break;
        }*/
        
        if (sine_index >= SINE_TABLE_SIZE) {
            sine_index = 0;
        }
    }
    else {
        sine_out_pin.write_u16(0);
    }
    
    switch (adc_sampling_frequency) {
        case ADC_SAMP_FREQ_1HZ:
            if (tick_count % 10000 == 0) {
                //read_adc();
                adc_buffer.write(my_analog_pin.read_u16(), ((long long) timer.read_us()) - offset);
            }
            break;
        case ADC_SAMP_FREQ_10HZ:
            if (tick_count % 1000 == 0) {
                //read_adc();
                adc_buffer.write(my_analog_pin.read_u16(), ((long long) timer.read_us()) - offset);
            }
            break;
        case ADC_SAMP_FREQ_100HZ:
            if (tick_count % 100 == 0) {
                //read_adc();
                adc_buffer.write(my_analog_pin.read_u16(), ((long long) timer.read_us()) - offset);
            }
            break;
        case ADC_SAMP_FREQ_OFF:
            // do nothing
            break;
    }
    
    if (d_out_on == D_OUT_ON) {
        d_out_pin = true;
    }
    else {
        d_out_pin = false;
    }
    
    
    if (tick_count % 100 == 0) {
        // update the display every 10 ms
        long long time_us = ((long long) timer.read_us()) - offset;
        int time_s = (int) (time_us / 1000000);
        int time_m = time_s / 60;
        
        int display_time = (time_m % 60) * 100 + (time_s % 60);
        //lcd.display(display_time);
        //lcd.putc('1');
        int display_time_ones = display_time % 10;
        int display_time_tens = (display_time / 10) % 10;
        int display_time_hund = (display_time / 100) % 10;
        int display_time_thou = (display_time / 1000) % 10;
        lcd.putc('0' + display_time_thou);
        lcd.putc('0' + display_time_hund);
        lcd.putc('0' + display_time_tens);
        lcd.putc('0' + display_time_ones);
    }
    
    tick_count++;
}

void send_light_sensor_data() {
    light_sensor_buffer.swapBuff();
    unsigned short* sensor_data = light_sensor_buffer.getReadBuffer();
    int sensor_data_size = light_sensor_buffer.getReadBufferSize();
    long long* ts = light_sensor_buffer.getTimestampReadBuffer();
    
    // send header
    pc.putc('l');
    send_int(sensor_data_size);

    for (int i = 0; i < sensor_data_size; i++) {
        send_ull(ts[i]);
        send_us(sensor_data[i]);
    }
}

void send_adc_data() {
    adc_buffer.swapBuff();
    unsigned short* adc_data = adc_buffer.getReadBuffer();
    int adc_data_size = adc_buffer.getReadBufferSize();
    long long* ts = adc_buffer.getTimestampReadBuffer();
    
    // send header
    pc.putc('a');
    send_int(adc_data_size);
    
    for (int i = 0; i < adc_data_size; i++) {
        send_ull(ts[i]);
        send_us(adc_data[i]);
    }
}

void send_timestamp_event_data() {
    d_event_buffer.swapBuff();
    long long* timestamp_data = d_event_buffer.getReadBuffer();
    int timestamp_data_size = d_event_buffer.getReadBufferSize();
    
    pc.putc('d');
    send_int(timestamp_data_size);
    
    for (int i = 0; i < timestamp_data_size; i++) {
        //unsigned long long ts = timestamp_data[i];
        //unsigned int msbs = ((unsigned int) (ts >> 32) & 0xffffffff);
        //unsigned int lsbs = ((unsigned int) ts & 0xffffffff);
        send_ull(timestamp_data[i]);
    }
}

void systick_attach() {
    tick_count = 0;
    sine_index = 0;
    //ticker.attach_us(&systick, 100000);
    ticker.attach_us(&systick, 100);
}

void d_event(){
    // take timestamp, send it to thingspeak later
    long long ts = timer.read_us() - offset;
    d_event_buffer.write(ts, ts);
}

int sync_timestamp = 0;
int tx_timestamp = 0;

// take a timestamp, save it in a global if it was an 's' character
void rx_sync_interrupt(MODSERIAL_IRQ_INFO *q) {
    sync_timestamp = timer.read_us();
}

void tx_interrupt(MODSERIAL_IRQ_INFO *q) {
    tx_timestamp = timer.read_us();
}

int main()
{
    redled = true; 
    timer.start();
    light_sensor_buffer.init(&offset, &timer);
    adc_buffer.init(&offset, &timer);
    d_event_buffer.init(&offset, &timer);
    //initialize hardware
    systick_attach();
    d_event_pin.rise(&d_event);
    pc.baud(19200);
    
    // set our interrupt to occur on receiving the sync packet
    //pc.attach(&rx_sync_interrupt, MODSERIAL::RxAutoDetect);
    //pc.autoDetectChar('s');
    //pc.attach(&tx_interrupt, MODSERIAL::TxIrq);
    
    // lower the priority of the systick, since it might interfere with our timestamping
    //NVIC_SetPriority(LPTimer_IRQn, 255);
    
    t1_string[30] = '\0';
    
    int i = 0;
    
    while (true) 
    {
        redled = false;
        char c = pc.getc();
        //redled = true;
        //pc.printf("got a char %c\r\n", c);
        t2 = timer.read_us();
        //t2 = sync_timestamp;
        // make sure we've gotten an 's', which we are using as
        // the sync message. If we get an 's' then t2 is correct.
        if (c != 's') {
            continue;
        }
        //pc.printf("got s\r\n");
        
        // we can drop the 's'
        c = pc.getc();
        i = 0;
        while (c != '\n' && i < 30) {
            t1_string[i] = c;
            c = pc.getc();
            i++;
        }
        t1_string[i] = '\0';
        i = 0;
        
        
        
        //char display_time[5];
        //display_time[0] = t1_string[3];
        //display_time[1] = t1_string[4];
        //display_time[2] = t1_string[6];
        //display_time[3] = t1_string[7];
        //display_time[4] = '\0';
        //int display_time_int = atoi(display_time);
        //lcd.display(display_time_int);
        //read_complete = true;
        
        //t3 = timer.read_us();
        // sending the delay_req message at time t3
        pc.putc('r');
        t3 = timer.read_us();
        
        // get the t4 packet
        c = pc.getc();
        i = 0;
        while (c != '\n' && i < 30) {
            t4_string[i] = c;
            c = pc.getc();
            i++;
        }
        t4_string[i] = '\0';
        i = 0;
        
        //pc.printf("t4str:  %s\n", t4_string);
        
        /*if (t4 == 0) {
            pc.printf("t4 is zero\n");
        }
        else {
            pc.printf("t4 is not zero\n");
        }*/
        
        //pc.printf("t4: %lld\n", t4);
        //lcd.display(7);
        //lcd.display(sizeof(long long) * 100 + sizeof(long));
        pc.printf("t1_string: %s t2: %d t3: %d t4_string: %s\n", t1_string, t2, t3, t4_string);
        
        long long t1 = atoll(t1_string);
        long long t4 = atoll(t4_string);
        pc.printf("t1: %lld t2: %d t3: %d t4: %lld\n", t1, t2, t3, t4);
        offset = (((long long) t2 - t1) - (t4 - (long long) t3)) / 2;
        pc.printf("offset: %lld\n", offset);
        
        //pc.printf("offset: %lld\n", offset);

        long long time_us = ((long long) timer.read_us()) - offset;
        long long time_s = time_us / 1000000;
        long long time_m = time_s / 60;
        long long time_h = time_m / 60;
        //pc.printf("time: %lld:%lld:%lld:%lld\n",  time_h % 24, time_m % 60, time_s % 60, time_us % 1000000);
        long long* lsdt1 = light_sensor_buffer.db_timestamps[0];
        long long* lsdt2 = light_sensor_buffer.db_timestamps[1];
        pc.printf("lsd[0][0] %lld [0][1] %lld [0][2] %lld [1][0] %lld [1][1] %lld [1][2] %lld\n", lsdt1[0], lsdt1[1], lsdt1[2], lsdt2[0], lsdt2[1], lsdt2[2]);
        
        
        // detach the systick, then reattach at the right time
        /*long long time_us_roundup = (time_s + 1) * 1000000;
        while((timer.read_us() - offset) < time_us_roundup) {
            // wait until the next second
        }
        ticker.detach();
        systick_attach();*/
        
        /*char onoff = pc.getc();
        switch(onoff) {
            case 'a':
                redled = false;
                break;
            case 'b':
                redled = true;
                break;
        }*/
        
        char opts = pc.getc();
        set_options(opts);
        
        // send adc data, timestamp event data, light sensor data
        send_adc_data();
        send_light_sensor_data();
        send_timestamp_event_data();
    }
}