Charlotte Latin 2020 Week 14 Group Assignment

Networking and Communications

Networking

Both Vincent Zhou's and William Zhou's networking project communicated through RS-232 UART, so we decided to connect the two projects together. We decided to print out the information from William's master board on Vincent's OLED screen.

The code only needed to be modified on Vincent's board, since William's board already transmits serial communications.

#define F_CPU 20000000

#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <stdlib.h>

#define setInputPin(pin) PORTA.DIRCLR |= (1 << pin)
#define setOutputPin(pin) PORTA.DIRSET |= (1 << pin)
#define setPinHigh(pin) VPORTA.OUT |= (1 << pin)
#define setPinLow(pin) VPORTA.OUT &= ~(1 << pin)
#define readPin(pin) VPORTA.IN & (1 << pin)

#define I2C_slave_address 0x78
#define I2C_delay() _delay_us(5)

#define TWI0_BAUD(F_SCL)      ((((float)F_CPU / (float)F_SCL)) - 10 )
void TWI_init()
{
    TWI0.MBAUD = (uint8_t)TWI0_BAUD(100000);  // Set MBAUD register for 100kHz
    TWI0.MCTRLA = 1 << TWI_ENABLE_bp          // Enable TWI Master: enabled
    | 0 << TWI_QCEN_bp                        // Quick Command Enable: disabled
    | 0 << TWI_RIEN_bp                        // Read Interrupt Enable: disabled
    | 1 << TWI_SMEN_bp                        // Smart Mode Enable: enabled
    | TWI_TIMEOUT_DISABLED_gc                 // Bus Timeout Disabled
    | 0 << TWI_WIEN_bp;                       // Write Interrupt Enable: disabled

    TWI0.MCTRLB |= TWI_FLUSH_bm;              // Purge MADDR and MDATA 
    TWI0.MSTATUS |= TWI_BUSSTATE_IDLE_gc;     // Force TWI state machine into IDLE state
    TWI0.MSTATUS |= (TWI_RIF_bm | TWI_WIF_bm);
}

uint8_t TWI_start(uint8_t deviceAddr)
{
    if ((TWI0.MSTATUS & TWI_BUSSTATE_gm) != TWI_BUSSTATE_BUSY_gc)   //Verify Bus is not busy
    {
    TWI0.MCTRLB &= ~(1 << TWI_ACKACT_bp);
    TWI0.MADDR = deviceAddr ;
    if (deviceAddr&0x01)  {while(!(TWI0.MSTATUS & TWI_RIF_bm));}  // If addressRead
    else                  {while(!(TWI0.MSTATUS & TWI_WIF_bm));}  // If addressWrite
    return 0;
    }
    else return 1;                                                  // Bus is busy
}

uint8_t TWI_read(uint8_t ACK)                                     // ACK=1 send ACK ; ACK=0 send NACK
{

    if ((TWI0.MSTATUS & TWI_BUSSTATE_gm) == TWI_BUSSTATE_OWNER_gc)  // Verify Master owns the bus
    {
    while(!(TWI0.MSTATUS & TWI_RIF_bm));                          // Wait until RIF set
    uint8_t data=TWI0.MDATA;
    if(ACK==1)  {TWI0.MCTRLB &= ~(1<<TWI_ACKACT_bp);}             // If ACK=1 Put 0 ACKACT => action send ack
    else        {TWI0.MCTRLB |= (1<<TWI_ACKACT_bp); }             // Else if (ACK=0) => put 1 ACKACT => nack prepared for actionstop

    return data ;
    }
    else
    return 1;                                                       //Master does not own the bus

}
uint8_t TWI_write(uint8_t write_data)
{
    if ((TWI0.MSTATUS&TWI_BUSSTATE_gm) == TWI_BUSSTATE_OWNER_gc)              // Verify Master owns the bus
    {
    TWI0.MDATA = write_data;
    while (!((TWI0.MSTATUS & TWI_WIF_bm) | (TWI0.MSTATUS & TWI_RXACK_bm))); // Wait until WIF set and RXACK cleared
    return 0;
    }
    else
    return 1;                                                                 // Master does not own the bus
}

void TWI_stop(void)
{
    TWI0.MCTRLB |= TWI_ACKACT_NACK_gc;
    TWI0.MCTRLB |= TWI_MCMD_STOP_gc;
}

// 
char TWI_master_write(unsigned char* data,unsigned char nbytes,unsigned char slave_address) 
{
    unsigned char index, ret, slave_address_write;
    
    // Send start and send slave address
    slave_address_write = slave_address << 1;
    if (TWI_start(slave_address) != 0)
    // No ACK,return 1
    return 1;
    
    // Loop over bytes
    for (index = 0; index < nbytes; ++index) {
    ret = TWI_write((data[index]));
    if (ret != 0) 
        // no ACK, return 1
        break;
    // yes ACK, continue
    }
    
    //Send stop
    TWI_stop();
    return ret;
}

static const uint8_t MonospaceBold7x8[] PROGMEM = {0,0,0,0,0,0,0,0,0,0,223,223,0,0,0,0,7,0,7,0,0,32,228,62,231,124,39,4,0,76,154,255,154,112,0,39,37,23,232,168,228,0,0,112,247,159,241,192,240,0,0,0,7,0,0,0,0,0,24,126,195,0,0,0,0,195,126,24,0,0,0,18,12,63,12,18,0,0,16,16,124,16,16,0,0,128,112,48,0,0,0,0,0,48,48,48,0,0,0,0,192,192,0,0,0,0,0,192,56,6,1,0,0,126,255,129,137,255,126,0,129,129,255,255,128,128,0,129,193,161,153,143,134,0,129,137,137,137,247,118,0,48,44,38,255,255,32,0,143,143,137,137,249,113,0,124,255,139,137,249,112,0,1,129,241,125,31,3,0,118,247,137,137,247,118,0,14,159,145,209,255,62,0,0,204,204,0,0,0,0,0,204,204,0,0,0,0,48,48,120,72,72,204,0,40,40,40,40,40,40,0,204,72,72,120,48,48,0,2,217,215,7,0,0,124,130,57,69,69,254,0,0,192,252,47,47,252,192,0,255,255,137,137,247,118,0,60,126,195,129,129,66,0,255,255,129,129,255,60,0,255,255,137,137,137,129,0,255,255,9,9,9,1,0,60,126,195,145,241,242,0,255,255,8,8,255,255,0,129,129,255,255,129,129,0,64,128,129,129,255,127,0,255,255,24,62,227,193,0,255,255,128,128,128,128,0,255,254,28,28,254,255,0,255,255,14,112,255,255,0,126,255,129,129,255,126,0,255,255,17,17,31,14,0,126,255,129,129,255,126,0,255,255,17,17,111,206,128,78,143,153,153,241,114,0,1,1,255,255,1,1,0,127,255,128,128,255,127,0,3,63,240,240,63,3,15,255,240,12,240,255,15,0,129,231,60,60,231,129,0,1,15,252,252,15,1,0,193,225,185,141,135,131,0,0,255,255,129,0,0,0,1,6,56,192,0,0,0,0,129,255,255,0,0,4,6,3,3,6,4,0,128,128,128,128,128,128,128,0,1,3,2,0,0,0,0,96,244,148,148,252,248,0,255,255,136,136,248,112,0,120,252,204,132,132,132,0,112,248,136,136,255,255,0,120,252,148,148,156,152,0,8,254,255,9,9,0,0,28,190,162,162,254,126,0,255,255,8,8,248,240,0,136,136,251,251,128,128,0,136,136,251,123,0,0,0,255,255,16,124,196,128,1,1,127,255,128,128,0,0,252,252,4,252,4,252,0,252,252,4,4,252,248,0,120,252,132,132,252,120,0,254,254,34,34,62,28,0,28,62,34,34,254,254,0,0,252,252,4,4,4,0,88,156,180,180,228,104,4,4,255,255,132,132,0,0,124,252,128,128,252,252,0,12,124,224,224,124,12,12,252,224,16,224,252,12,0,132,204,120,120,204,132,0,130,142,248,56,14,2,0,196,228,164,148,156,140,0,16,16,239,239,129,129,0,0,0,255,0,0,0,0,129,129,239,239,16,16,0,16,16,16,32,32,32};

static const uint8_t MonospaceBold10x16lo[] PROGMEM = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,254,0,0,0,0,0,0,30,30,0,0,30,30,0,0,0,48,176,248,62,50,240,254,62,48,0,112,248,216,254,152,152,0,0,0,28,34,162,162,156,64,64,32,32,0,0,0,220,126,230,198,134,12,128,128,0,0,0,0,30,30,0,0,0,0,0,0,0,224,252,30,2,0,0,0,0,0,2,30,252,224,0,0,0,0,0,72,120,48,254,48,120,72,0,0,0,128,128,128,240,240,128,128,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,240,60,14,2,0,0,240,252,14,198,198,14,252,248,0,0,0,12,6,254,254,0,0,0,0,0,12,6,6,6,134,198,124,56,0,0,12,6,198,198,198,198,252,56,0,0,128,192,112,24,14,254,254,0,0,0,254,126,102,102,102,230,198,128,0,0,240,252,206,102,102,230,204,128,0,0,6,6,6,6,230,254,62,14,0,0,56,252,198,198,198,198,252,56,0,0,120,252,206,134,134,206,252,248,0,0,0,0,0,224,224,0,0,0,0,0,0,0,0,224,224,0,0,0,0,0,128,128,192,64,96,96,32,48,0,0,96,96,96,96,96,96,96,96,0,0,48,32,96,96,64,192,128,128,0,0,12,6,134,198,102,126,28,0,0,224,240,56,156,204,204,220,248,240,0,0,0,192,252,62,62,252,192,0,0,0,254,254,198,198,198,198,252,60,0,0,240,252,12,6,6,6,6,12,0,0,254,254,6,6,6,12,252,240,0,0,254,254,198,198,198,198,198,6,0,0,254,254,198,198,198,198,198,6,0,0,240,252,12,6,134,134,134,140,0,0,254,254,192,192,192,192,254,254,0,0,0,6,6,254,254,6,6,0,0,0,0,0,0,6,6,6,254,254,0,0,254,254,224,240,252,14,6,2,0,0,254,254,0,0,0,0,0,0,0,0,254,254,62,240,240,62,254,254,0,0,254,254,30,240,192,0,254,254,0,0,240,252,14,6,6,14,252,240,0,0,254,254,198,198,198,198,124,124,0,0,240,252,14,6,6,14,252,240,0,0,254,254,198,198,198,198,252,60,0,0,56,124,230,198,198,198,140,0,0,0,6,6,6,254,254,6,6,6,0,0,254,254,0,0,0,0,254,254,0,0,6,254,252,0,0,252,254,6,0,30,254,224,0,240,240,0,224,254,30,0,2,14,62,248,248,62,14,2,0,2,14,62,120,224,224,120,62,14,2,0,6,6,134,198,246,126,30,14,0,0,0,0,254,254,2,2,0,0,0,0,2,14,56,224,128,0,0,0,0,0,0,2,2,254,254,0,0,0,0,16,24,28,14,6,14,28,24,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,6,4,0,0,0,0,0,0,96,48,176,176,176,240,224,0,0,254,254,96,48,48,112,224,192,0,0,192,224,112,48,48,48,48,96,0,0,192,224,112,48,48,96,254,254,0,0,192,224,176,176,176,176,224,192,0,0,48,48,252,254,54,54,54,0,0,0,192,224,112,48,48,96,240,240,0,0,254,254,96,48,48,48,240,224,0,0,0,48,48,247,247,0,0,0,0,0,0,48,48,247,247,0,0,0,0,0,254,254,128,224,112,48,16,0,0,0,6,6,254,254,0,0,0,0,0,0,240,240,48,240,224,48,240,224,0,0,240,240,96,48,48,48,240,224,0,0,192,224,112,48,48,112,224,192,0,0,240,240,96,48,48,112,224,192,0,0,192,224,112,48,48,96,240,240,0,0,0,240,240,96,48,48,48,48,0,0,224,240,176,176,176,176,48,96,0,0,48,48,252,252,48,48,48,0,0,0,240,240,0,0,0,0,240,240,0,0,48,240,224,0,0,224,240,48,0,112,240,0,0,192,192,0,0,240,112,0,16,48,240,192,192,240,48,16,0,0,16,240,240,128,0,240,240,48,0,0,48,48,48,48,176,240,112,48,0,0,0,0,0,252,254,2,2,0,0,0,0,0,0,254,254,0,0,0,0,0,0,2,2,254,252,0,0,0,0,0,128,192,192,192,128,128,128,192,0,0,0,0,0};

static const uint8_t MonospaceBold10x16hi[] PROGMEM = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,25,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,27,31,3,3,31,15,3,3,0,0,12,24,24,127,25,31,15,0,0,1,1,0,0,14,17,17,17,14,0,0,7,15,28,24,25,31,30,31,19,0,0,0,0,0,0,0,0,0,0,0,0,0,7,63,120,64,0,0,0,0,0,64,120,63,7,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,1,15,15,1,1,1,0,0,0,0,64,124,60,0,0,0,0,0,0,3,3,3,3,3,0,0,0,0,0,0,0,28,28,0,0,0,0,0,32,56,30,7,1,0,0,0,0,0,3,15,28,24,24,28,15,7,0,0,24,24,24,31,31,24,24,24,0,0,24,28,30,27,25,24,24,24,0,0,12,24,24,24,24,25,15,15,0,0,3,3,3,3,3,31,31,3,0,0,12,24,24,24,24,28,15,7,0,0,7,15,28,24,24,28,15,7,0,0,0,16,28,15,3,0,0,0,0,0,15,15,24,24,24,24,15,15,0,0,0,12,25,25,25,28,15,3,0,0,0,0,0,28,28,0,0,0,0,0,0,0,64,124,60,0,0,0,0,0,1,1,3,2,6,6,4,12,0,0,6,6,6,6,6,6,6,6,0,0,12,4,6,6,2,3,1,1,0,0,0,0,27,27,0,0,0,0,0,7,31,56,115,103,102,102,119,39,0,0,24,31,15,3,3,15,31,24,0,0,31,31,24,24,24,24,31,15,0,0,3,15,12,24,24,24,24,12,0,0,31,31,24,24,24,12,15,3,0,0,31,31,24,24,24,24,24,24,0,0,31,31,0,0,0,0,0,0,0,0,3,15,12,24,25,25,31,15,0,0,31,31,0,0,0,0,31,31,0,0,0,24,24,31,31,24,24,0,0,0,12,24,24,24,24,24,15,15,0,0,31,31,0,0,3,15,30,24,0,0,31,31,24,24,24,24,24,24,0,0,31,31,0,1,1,0,31,31,0,0,31,31,0,0,3,30,31,31,0,0,3,15,28,24,24,28,15,3,0,0,31,31,0,0,0,0,0,0,0,0,3,15,28,24,24,60,111,7,0,0,31,31,0,0,1,3,31,30,16,0,12,24,24,24,24,25,15,15,0,0,0,0,0,31,31,0,0,0,0,0,7,15,28,24,24,28,15,7,0,0,0,0,31,31,31,31,0,0,0,0,31,31,30,1,1,30,31,31,0,0,16,28,31,3,3,31,28,16,0,0,0,0,0,31,31,0,0,0,0,0,28,30,31,27,24,24,24,24,0,0,0,0,127,127,64,64,0,0,0,0,0,0,0,0,3,14,56,32,0,0,0,64,64,127,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,31,27,25,25,13,31,31,0,0,31,31,12,24,24,28,15,7,0,0,7,15,28,24,24,24,24,12,0,0,7,15,28,24,24,12,31,31,0,0,7,15,29,25,25,25,25,13,0,0,0,0,31,31,0,0,0,0,0,0,7,111,220,216,216,204,255,127,0,0,31,31,0,0,0,0,31,31,0,0,24,24,24,31,31,24,24,24,0,0,192,192,192,255,127,0,0,0,0,0,31,31,1,3,7,30,24,16,0,0,0,0,15,31,24,24,24,0,0,0,31,31,0,31,31,0,31,31,0,0,31,31,0,0,0,0,31,31,0,0,7,15,28,24,24,28,15,7,0,0,255,255,12,24,24,28,15,7,0,0,7,15,28,24,24,12,255,255,0,0,0,31,31,0,0,0,0,0,0,0,12,25,25,25,25,27,31,14,0,0,0,0,15,31,24,24,24,0,0,0,15,31,24,24,24,12,31,31,0,0,0,1,15,30,30,15,1,0,0,0,7,31,30,3,3,30,31,7,0,0,16,24,30,7,7,30,24,16,0,0,0,192,195,255,63,15,1,0,0,0,24,28,30,27,25,24,24,24,0,0,0,1,1,126,254,128,128,0,0,0,0,0,0,255,255,0,0,0,0,0,0,128,128,254,126,1,1,0,0,0,1,0,0,0,1,1,1,0,0,0,0,0,0};

void OLEDcommand(uint8_t c) {
    static uint8_t data[2];
    data[0] = 0;
    data[1] = c;
    TWI_master_write(data,2,I2C_slave_address);
}

void OLEDcommands(uint8_t c1,uint8_t c2) {
    static uint8_t data[3];
    data[0] = 0;
    data[1] = c1;
    data[2] = c2;
    TWI_master_write(data,3,I2C_slave_address);
}

void OLEDdata(uint8_t d) {
    static uint8_t data[2];
    data[0] = 0x40;
    data[1] = d;
    TWI_master_write(data,2,I2C_slave_address);
}

void OLED7x8string(uint8_t row,uint8_t col,char str[]) {
    static uint8_t index,offset,pointer;
    static char chr;
    OLEDcommands(0x00+(col & 0x0F),0x10+((col >> 4) & 0x0F));
    OLEDcommand(0xB0+row);
    index = 0;
    while (1) {
    chr = str[index];
    if (chr == '\0') break;
    pointer = chr-' ';
    for (offset = 0; offset < 7; ++offset) {
        OLEDdata(pgm_read_byte(&(MonospaceBold7x8[7*pointer+offset])));
    }
    ++index;
    }
}

void OLED10x16string(uint8_t row,uint8_t col,char str[]) {
    static uint8_t index,offset,pointer;
    static char chr;
    OLEDcommands(0x00+(col & 0x0F),0x10+((col >> 4) & 0x0F));
    OLEDcommand(0xB0+row);
    index = 0;
    while (1) {
    chr = str[index];
    if (chr == '\0') break;
    pointer = chr-' ';
    for (offset = 0; offset < 10; ++offset) {
        OLEDdata(pgm_read_byte(&(MonospaceBold10x16lo[10*pointer+offset])));
    }
    ++index;
    }
    OLEDcommands(0x00+(col & 0x0F),0x10+((col >> 4) & 0x0F));
    OLEDcommand(0xB0+row+1);
    index = 0;
    while (1) {
    chr = str[index];
    if (chr == '\0') break;
    pointer = chr-' ';
    for (offset = 0; offset < 10; ++offset) {
        OLEDdata(pgm_read_byte(&(MonospaceBold10x16hi[10*pointer+offset])));
    }
    ++index;
    }
    }
void OLED128x64init() {
    uint8_t i,j;
    //Init TWI
    TWI_init();
    
    //Init SSD1306
    OLEDcommand(0xae);       // Display off
    OLEDcommands(0xa8,0x3f); // Set multiplex ratio, ratio 63
    OLEDcommands(0xd3,0x00); // Set display offset, no offset
    OLEDcommand(0x40);       // Set display start line
    OLEDcommand(0xa1);       // Set segment remap col 127 to seg 0
    OLEDcommand(0xc8);       // Set COM output reverse
    OLEDcommands(0xda,0x12); // COM pin config, alt bottom to top
    OLEDcommands(0x81,0xff); // Set contrast, max contrast
    OLEDcommand(0xa4);       // Resume to RAM display
    OLEDcommand(0xa6);       // Normal non-inverted display
    OLEDcommands(0xd5,0x80); // Set clock divider, default
    OLEDcommands(0x8d,0x14); // Set charge pump, enable
    OLEDcommands(0x20,0x02); // Set memory mode, page addressing
    OLEDcommand(0xaf);       // Display on
    //
    // clear screen
    //
    for (j = 0; j < 8; ++j) {
    OLEDcommands(0x00,0x10);
    OLEDcommand(0xB0+j);
    for (i = 0; i < 128; ++i) OLEDdata(0);
    }
}

void setup() {
    OLED128x64init();
    Serial.begin(115200);
}

void loop() {
    char str[32];
    //int node, LEDNum, red, green, blue;
    if (Serial.available()) {
    int availableBytes = Serial.available();
    for (int i = 0; i < availableBytes; i++) {
        str[i] = Serial.read();
    }
//    char node = strtok(str, ":")[1];
//    char LEDNum = strtok(NULL, ":")[1];
//    red = atoi(strtok(NULL, ":"));
//    green = atoi(strtok(NULL, ":"));
//    blue = atoi(strtok(NULL, ":"));


    char* ptr;

    String line1 = "Node: ";
    long node = strtol(strtok(str, ":"), &ptr, 10);
    line1.concat(node);

    
    String line2 = "Num: ";
    
    long num = strtol(strtok(NULL, ":"), &ptr, 10);
    line2.concat(num);

    strtok(NULL, ":");
    strtok(NULL, ":");
    strtok(NULL, ":");
    
    char line1Char [10];
    char line2Char [10];
    
    line1.toCharArray(line1Char, 10);
    line2.toCharArray(line2Char, 10);
    
    OLED7x8string(1, 0, line1Char);
    OLED7x8string(2, 0, line2Char);
    }
}
            

However, the problem with RS-232 communcations is that it was designed for communications between two devices. William's networking project uses RS-232 communications to trasmit LED color information to the LED slave boards. With the addition of Vincent's board, the received data was somtimes corrupted or impartial and, as a consequence, would not always display LED data correctly on the OLED display. Unfortunately, no one else in the group had used other communications besides RS-232, so we had to make do with the current results.