/* Recv Code - clock rate determined by Tx */
#include <LiquidCrystal_I2C.h>
#define RX_CLOCK 2
#define RX_DATA 3
LiquidCrystal_I2C lcd(0x27,16,2);
char message[20];
volatile byte rx_byte = 0;
volatile int bit_position = 0;
volatile bool update_lcd = true;
Like the Tx code, we need the LCD library to connect via I2C bus. We predefine an array for 20 characters - the size of the LCD line. The variables start with "volatile" because they are part of an interrupt.
void setup() {
lcd.init();
lcd.backlight();
pinMode(RX_DATA, INPUT);
strcpy(message, "");
attachInterrupt(digitalPinToInterrupt(RX_CLOCK), onClockPulse, RISING);
} // end setup
void onClockPulse() {
bool rx_bit = digitalRead(RX_DATA);
if (bit_position == 8) {
rx_byte = 0;
bit_position = 0;
}
if (rx_bit) {
rx_byte |= (0x80 >> bit_position);
}
bit_position += 1;
if (bit_position == 8) {
strncat(message, &rx_byte, 1);
}
update_lcd = true;
} // end onClockPulse interrupt service routine
The above interrupt handler is triggered by and incoming clock. The "if(rx_bit)" when true, will be a "1", so the rx_byte will have a "1" placed in it by ORing the 1000 0000, bit_position starts out a zero. As the bits are read in, each is placed in the message array.
void loop() {
if (update_lcd) {
update_lcd = false;
lcd.noCursor();
lcd.setCursor(0, 0);
lcd.print(message);
lcd.setCursor(0, 1);
for (int i = 0; i < 8; i += 1) {
if (i < bit_position) {
lcd.print(rx_byte & (0x80 >> i) ? "1" : "0");
} else {
lcd.print(" ");
}
}
lcd.setCursor(strlen(message) - 1, 0);
lcd.cursor();
These lines are only here to bring the cursor back to the last letter to match the Tx message.
} // end if statement
} // end loop