Add I2CSlave to ov580 master.

Dependencies:   MorseGenerator2

main.cpp

Committer:
claytonk
Date:
2018-10-30
Revision:
8:10ffd42a3921
Parent:
7:9c77eaad5102
Child:
9:69e0bbfdb62b

File content as of revision 8:10ffd42a3921:

#define TWIS1_ENABLED 1
#define TWIS0_ENABLED 0
#define TWIS_ENABLED 1
#define TWI0_ENABLED 1
#define TWI1_ENABLED 0
#define TWI0_USE_EASY_DMA 1
#define TWI1_USE_EASY_DMA 1
#define TWI_DEFAULT_CONFIG_FREQUENCY 104857600
#define ARDUINO_A4_PIN  14
#define ARDUINO_A5_PIN  15


#include "mbed.h"
//#include <nrfx_config.h>  need SDK config instead
//#include "sdk_config.h" not needed now

/*
FEATURE REQUIREMENTS

-   I2C write occurs on falling edge of strobe pulse to prevent unknown states

-   Stack check occurs on leading edge of strobe pulse to ensure strobes are
    set correctly

-   Reoccuring enable from app that will prevent the emitters from remaining
    on if the app crashes and a turn off command isn't sent
    - Can be a counter on the emitter enable > threshold
    - Better if it's a counter based on reads from the fault register

-Flood/Dot tagging indicated on GPIO3
    - 0 Flood
    - 1 DOT

-Fault indication on GPIO4 to indicate to app to reboot
    - 0 OK
    - 1 Fault/Reboot

I2C write commands
Reg:        Information             Condition
0x0000      Emitter enable          0x00        Emitters off
                                    0x01        Dot on
                                    0x10        Flood on
                                    0x11        Flood / Dot on

0x0001      Dot fault               Read from LM36011

0x0002      Dot Current             0x00 - level_dot_max

0x0003      Flood Fault             Read from LM36011

0x0004      Flood Current           0x00 - level_flood_max

0x0005      Fault register          bit[0]      KILL_VCSEL fault
                                    bit[1]      dot fault
                                    bit[2]      flood fault
                                    bit[3]      unstacked fault
                                    bit[4]      ?not in app fault?
                                    bit[5-7]    unused


0x0006      Version number          0x70        = version 7.0

*/

#if (TWIS0_ENABLED == 1)
#error TWIS0 is congigured wrong
#endif

#if (TWIS1_ENABLED == 0)
#error TWIS1 is off
#endif

#if (TWIS_ENABLED == 0)
#error TWIS is off
#endif

#if (TWI0_ENABLED == 0)
#error TWI0 is off
#endif

#if (TWI1_ENABLED == 1)
#error TWI1 is congigured wrong
#endif

/*          DEFINES         */

#define version_number 0x70

// define pins for I2C
#define dot_sda p2
#define dot_scl p4
#define flood_sda p28
#define flood_scl p3
#define ov580_sda p30
#define ov580_scl p31

// define strobe pins
#define strobe_flood p23      // strobe0
#define strobe_dot p24    // strobe1

// define pmw pins
#define pwm_1_pin p29
#define pwm_0_pin p5

// define LED pins
#define ledRed p12
#define ledGreen p17
#define ledBlue p13

/*          THREAD          */
EventQueue queue;

/*          TIMOUT          */
Timeout dot_timeout;
Timeout flood_timeout;

/*          INTERRUPTS      */
//create interupts
InterruptIn int_strobe_dot(strobe_dot);
InterruptIn int_strobe_flood(strobe_flood);  // only need one interrupt in

/*          I/O            */
// initialize LEDs
DigitalOut red(ledRed,1);
DigitalOut green(ledGreen,1);
DigitalOut blue(ledBlue,1);

// Initialize outputs
DigitalOut pwm_0_output(pwm_0_pin,0);          // GPIO 3
DigitalOut pwm_1_output(pwm_1_pin,0);          // GPIO 4

// Initialize inputs
DigitalIn strobe0(strobe_flood,PullNone);
DigitalIn strobe1(strobe_dot,PullNone);
DigitalIn vcselFault(p25,PullNone);
DigitalIn killVcsel(p26,PullNone);  // vcselFault is 1V8 instead of 3V3


/*          REGISTERS       */
static uint8_t LM36011_addr = 0x64 << 1;  //0xC8

// register names
static uint8_t enable_reg = 0x01;
static uint8_t configuration_reg = 0x02;
static uint8_t brightness_reg = 0x03;
//static uint8_t torch_reg = 0x04;
//static uint8_t flags_reg = 0x05;
//static uint8_t device_id_reset_reg = 0x06;

// register settings
static uint8_t enable_ir = 0x05;
static uint8_t disable_ir = 0x20;
static uint8_t enable_flash_timeout = 0x01;

// level settings
static uint8_t level_flood_max = 0x66;      // = 1.2 A
static uint8_t level_dot_max = 0x5F;      // = 1.03 A
//static uint8_t level_dot_max = 0x3F;      // = 0.75 A
//static uint8_t level_dot_max = 0x3C;      // = 0.70 A
//static uint8_t level_dot_max = 0x15       //0.257 A
//static uint8_t level_dot_max = 0x1F;        // =  352mA

char lm_on[2] = {enable_reg,enable_ir};
char lm_off[2] = {enable_reg,disable_ir};
char lmSafety[2] = {configuration_reg,enable_flash_timeout};

char flashBrightness_dot[2] = {brightness_reg,level_dot_max};
char flashBrightness_flood[2] = {brightness_reg,level_flood_max};

/*          I2C             */
I2CSlave ov_I2C(ov580_sda,ov580_scl);
I2C flood_I2C(flood_sda,flood_scl);
I2C dot_I2C(dot_sda,dot_scl);


/*          VARIABLES       */
bool stacked = false;
bool emitter_status_dot = false;
char rcv_buffer[3] = {0,0,0};
int dot_counter = 0;
bool dot_on = false;
int flood_counter = 0;
bool flood_on = false;
bool once = false;
bool in_app = false;
int app_counts_required = 10;
int stacked_counter = 0;

/*          FUNCTIONS       */

// WAI
void write_off()
{
    dot_I2C.write(LM36011_addr,lm_off,2,false);
    flood_I2C.write(LM36011_addr,lm_off,2,false);
}

// WAI
void write_dot()
{
    flood_I2C.write(LM36011_addr,lm_off,2,false);
    dot_I2C.write(LM36011_addr,lm_on,2,false);
}

// WAI
void write_flood()
{
    dot_I2C.write(LM36011_addr,lm_off,2,false);
    flood_I2C.write(LM36011_addr,lm_on,2,false);
}

// WAI
void write_pulsed()
{
    if(emitter_status_dot) {
        write_dot();
    } else {
        write_flood();
    }
}

// WAI
void write_once()
{
    if(in_app) {
        if(stacked_counter > app_counts_required) {
            write_pulsed();
            write_pulsed();
        } else {
            if(dot_on) {
                write_dot();
                write_dot();
            } else if(flood_on) {
                write_flood();
                write_flood();
            } else {
                write_off();
                write_off();
            }
        }
    } else {
        write_off();
        write_off();
    }
}

void dot_watchdog()
{
    dot_on = false;
    dot_counter = 0;
    stacked_counter = 0;
    stacked = false;
    queue.call(&write_once);
}

void flood_watchdog()
{
    flood_on = false;
    flood_counter = 0;
    stacked_counter = 0;
    stacked = false;
    queue.call(&write_once);
}

void dot_falling_edge()
{

    if(stacked) {
        emitter_status_dot = !emitter_status_dot;
    } else {
        emitter_status_dot = dot_on;
    }
    // indicate status dot
    pwm_0_output = emitter_status_dot;
    // indicate VCSEL fault if it exists
    pwm_1_output = !vcselFault.read();

    // write once
    queue.call(&write_once);

    // timeout for app exit
    dot_timeout.attach(&dot_watchdog,.05);
}

void flood_falling_edge()
{
    if (!stacked) {
        emitter_status_dot = dot_on;
    }
    // indicate status dot
    pwm_0_output = emitter_status_dot;
    // indicate VCSEL fault if it exists
    pwm_1_output = !vcselFault.read();
    // timeout for app exit
    //timeout.attach(&write_off,.5);
    // write once
    queue.call(&write_once);

    // timeout for app exit
    flood_timeout.attach(&flood_watchdog,.05);

}

void dot_check()
{
    dot_timeout.detach();

    dot_counter ++;
    if(dot_counter > app_counts_required) {
        dot_on = true;
    } else {
        dot_on = false;
    }
    stacked = strobe0.read();
    if(stacked) {
        stacked_counter++;
    } else {
        stacked_counter = 0;
        flood_counter = 0;
        flood_on = false;
    }
    if(!in_app) {
        if (stacked_counter > app_counts_required) {
            in_app = true;
        }
    }
}


void flood_check()
{
    flood_timeout.detach();

    flood_counter ++;
    if(flood_counter > app_counts_required) {
        flood_on = true;
    } else {
        flood_on = false;
    }
    stacked = strobe1.read();
    if(stacked) {
        stacked_counter++;
    } else {
        stacked_counter = 0;
        dot_counter = 0;
        dot_on = false;
    }
    if(!in_app) {
        if (stacked_counter > app_counts_required) {
            in_app = true;
        }
    }
}

//     TODOS    //
//  DONE    P0  Get illumination working
//  P0  Get OV580 I2C to look correct. Suspect open drain culprit
//  P0  Ensure that current implementation meets the needs of data collection
//  DONE    P0  Get in app working
//  DONE    P0  Get watchdog time working
//  DONE    P0      Check watchdog for working on dot and flood
//  P1  Bluetooth OTA updates
//  P2  Get writing working
//  P2  Get reading working
//

// main() runs in its own thread in the OS
int main()
{

    //wait(5);

    Thread eventThread(osPriorityHigh);;
    eventThread.start(callback(&queue, &EventQueue::dispatch_forever));

    // set interrupts
    int_strobe_dot.rise(&dot_check);
    int_strobe_flood.rise(&flood_check);
    int_strobe_dot.fall(&dot_falling_edge);
    int_strobe_flood.fall(&flood_falling_edge);

    while(!in_app) {
        red = 0;
    }
    green = !in_app;
    red = in_app;

    // set I2C Frequency to 400kHz
    //flood_I2C.frequency(400000);      not needed cause of set defaults
    //dot_I2C.frequency(400000);        not needed cause of set defaults
    //ov_I2C.frequency(400000);

    //TODO get i2c writes working
    //ov_I2C.address(0xC0);

    // write safety
    flood_I2C.write(LM36011_addr,lmSafety,2,false);
    dot_I2C.write(LM36011_addr,lmSafety,2,false);

    // write brightness
    flood_I2C.write(LM36011_addr,flashBrightness_flood,2,false);
    dot_I2C.write(LM36011_addr,flashBrightness_dot,2,false);

    while (true) {

        green = !in_app;
        red = in_app;

    }
}