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.