add 'lcd' library (LCDWrapper) that implements formatting + autoscroll | use rich formatting in entrypoints (.ino) | make well routine#0 to be non-blocking before each WAVE_TIMEOUT | add well routine#1 to receive and print messages

This commit is contained in:
Adrien Marquès 2018-12-04 09:43:11 +01:00
parent 373ecc6b32
commit cbe48ceebc
9 changed files with 155 additions and 102 deletions

72
lcd.h Normal file
View File

@ -0,0 +1,72 @@
#ifndef _LCD_H_
#define _LCD_H_
#include <LiquidCrystal_I2C.h>
class LCDWrapper {
private:
LiquidCrystal_I2C *display;
size_t cursor;
uint8_t cols;
uint8_t rows;
public:
LCDWrapper(uint8_t addr, uint8_t cols, uint8_t rows){
rows = rows;
cols = cols;
*display = LiquidCrystal_I2C(addr, cols, rows, LCD_5x8DOTS);
cursor = 0;
}
~LCDWrapper(){ display = NULL; }
void begin(){
display->begin();
display->backlight();
display->home();
clear();
}
void move(const uint8_t line, const uint8_t c){ display->setCursor(line, c); }
void clear(){ cursor = 0; display->clear(); }
void printf(const char *fmt, ...){
va_list va;
va_start(va, fmt);
char buffer[34] = {0};
int size = sprintf(buffer, fmt, va);
va_end(va);
display->print(buffer);
}
void printfn(const uint8_t line, const char *fmt, ...){
va_list va;
va_start(va, fmt);
char buffer[34] = {0};
int size = sprintf(buffer, fmt, va);
va_end(va);
display->setCursor(0,line);
display->print(buffer);
}
void printfn_overflow(const uint8_t line, const char *fmt, ...){
va_list va;
va_start(va, fmt);
char buffer[34] = {0};
int size = sprintf(buffer, fmt, va);
va_end(va);
display->setCursor(0,line);
display->print(buffer);
for( uint8_t offset = 0 ; size-offset > cols ; offset++ ){
delay(50);
display->setCursor(0,line);
display->print(buffer+offset);
}
}
};
#endif

1
node/main/lcd.h Symbolic link
View File

@ -0,0 +1 @@
../../lcd.h

View File

@ -1,27 +1,23 @@
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "lcd.h"
#include "packet.h" // Packet
#include "xbee_wrapper.h" // WBeeWrapper
// Peripherals
LiquidCrystal_I2C screen(0x20, 16, 2);
LCDWrapper screen = LCDWrapper(0x20, 16, 2);
XBeeWrapper xbee = XBeeWrapper();
// ACTUAL DATA
uint8_t wave_id = 255; // last wave
uint8_t dist = 255; // actual distance
Packet recv;
Packet send;
Packet recv, send;
void setup() {
Serial.begin(38400);
Serial.println("+ ready");
screen.begin();
screen.backlight();
screen.home();
screen.setCursor(0, 0);
screen.print("ready");
screen.printf("[ node ready ]");
xbee.begin(38400);
@ -43,82 +39,50 @@ void loop() {
if( recv.getDist() == 0 && recv.getSender() != 255 )
return;
screen.printfn(0, "dsc[%3d] %3d / %3d", recv.getSender(), recv.getDist(), recv.getWave());
status(wave_id, dist);
screen.print("dsc");
screen.print("[");
screen.print(recv.getSender());
screen.print("] -> ");
screen.print(recv.getDist());
screen.print("/");
screen.print(recv.getWave());
if( recv.getWave() != wave_id ){
wave_id = recv.getWave();
dist = recv.getDist()+1;
status(wave_id, dist);
screen.print("propagated");
delay(100);
send.setOpcode(0);
send.setWave(wave_id);
send.setDist(dist);
send.setSender(42);
xbee.broadcast(send);
Serial.print(" + send discover[");
Serial.print(send.getSender());
Serial.print("] -> ");
Serial.print(send.getDist());
Serial.print(" / ");
Serial.println(send.getWave());
// ignore if same wave
if( recv.getWave() == wave_id ){
screen.printfn(1, "x");
return;
}
// update features
wave_id = recv.getWave();
dist = recv.getDist()+1;
// propagate wave
send.setOpcode(0);
send.setWave(wave_id);
send.setDist(dist);
send.setSender(42);
screen.printfn(1, "dsc[%3d] %3d / %3d", send.getSender(), send.getDist(), send.getWave());
xbee.broadcast(send);
// MESSAGE DATA
} else {
screen.clear();
screen.setCursor(0,0);
screen.print("message(");
screen.print(recv.getDist());
screen.print(",");
screen.print(recv.getTTL());
screen.print(",");
screen.print(recv.getSize());
screen.print(")");
screen.setCursor(0,1);
screen.print( (char*)recv.getData());
delay(600);
screen.printfn(0, "msg[%3d/%3d] %3d", recv.getDist(), recv.getTTL(), recv.getSize());
delay(500);
screen.printfn_overflow(0, "%s", recv.getData());
// ignore
if( recv.getTTL() <= 0 || recv.getDist() > dist ){
screen.printfn(1, "x");
return;
}
// propagation
if( recv.getTTL() > 0 && recv.getDist() <= dist ){
send.setOpcode(1);
send.setTTL(recv.getTTL()-1);
send.setDist(dist);
send.setData(recv.getData(), recv.getSize());
xbee.broadcast(send);
Serial.print(" + send message(");
Serial.print(recv.getDist());
Serial.print(", ");
Serial.print(recv.getTTL());
Serial.print(", ");
Serial.print(recv.getSize());
Serial.println(")");
}
send.setOpcode(1);
send.setTTL(recv.getTTL()-1);
send.setDist(dist);
send.setData(recv.getData(), recv.getSize());
screen.printfn(1, "msg[%3d/%3d] %3d", send.getDist(), send.getTTL(), send.getSize());
xbee.broadcast(send);
}
}
void status(uint8_t wave, uint8_t dist){
screen.clear();
screen.setCursor(0,0);
screen.print(dist);
screen.print(" / ");
screen.print(wave);
screen.setCursor(0,1);
}

View File

@ -4,7 +4,7 @@
/* PUBLIC
----------------------------------------*/
// builds a packet from raw data and returns the error code
uint8_t Packet::read(uint8_t buf[], size_t size){
uint8_t Packet::read(uint8_t buf[], const size_t size){
// 1. fail on invalid size
if( size < 1 ) return PKTREAD_EMPTY;
if( size > PROTO_SIZE ) return PKTREAD_OVERFLOW;
@ -51,7 +51,7 @@ void Packet::setData(uint8_t *buffer, uint8_t size) { memcpy(msg.data, buffer, s
/* PRIVATE
----------------------------------------*/
uint8_t Packet::read_discover(uint8_t buf[], size_t size){
uint8_t Packet::read_discover(uint8_t buf[], const size_t size){
// 1. fail on invalid size
if( size != DISCOVER_SIZE )
return PKTREAD_INVALID_DISCOVER_FORMAT;
@ -64,7 +64,7 @@ uint8_t Packet::read_discover(uint8_t buf[], size_t size){
return PKTREAD_OK;
};
uint8_t Packet::read_message(uint8_t buf[], size_t size){
uint8_t Packet::read_message(uint8_t buf[], const size_t size){
// 1. fail on invalid size
if( size < MESSAGE_MIN_SIZE || size > MESSAGE_MAX_SIZE )
return PKTREAD_INVALID_MESSAGE_FORMAT;

View File

@ -20,14 +20,14 @@
struct message msg;
// 3. helpers
uint8_t read_discover(uint8_t buf[], size_t size);
uint8_t read_message(uint8_t buf[], size_t size);
uint8_t read_discover(uint8_t buf[], const size_t size);
uint8_t read_message(uint8_t buf[], const size_t size);
size_t write_discover(uint8_t buf[]);
size_t write_message(uint8_t buf[]);
public:
// builds a packet from raw data and returns the status code
uint8_t read(uint8_t buf[], size_t size);
uint8_t read(uint8_t buf[], const size_t size);
// writes the binary representation of the packet returns the size
size_t write(uint8_t buf[]);

1
well/main/lcd.h Symbolic link
View File

@ -0,0 +1 @@
../../lcd.h

View File

@ -1,48 +1,63 @@
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "lcd.h"
#include "xbee_wrapper.h"
#include "packet.h"
#define WAVE_TIMEOUT 5000
// Peripherals
LiquidCrystal_I2C screen(0x20, 16, 2);
LCDWrapper screen(0x20, 16, 2);
XBeeWrapper xbee = XBeeWrapper();
// ACTUAL DATA
uint8_t wave_id = 250;
Packet send;
Packet recv, send;
unsigned long time;
void setup() {
Serial.begin(38400);
Serial.println("+ ready");
screen.begin();
screen.backlight();
screen.home();
screen.setCursor(0,0);
screen.print("ready");
screen.printf("[ well ready ]");
xbee.begin(38400);
time = millis();
}
void loop() {
delay(WAVE_TIMEOUT);
/* [1] if WAVE_TIMEOUT reached */
if( millis() - time >= WAVE_TIMEOUT ){
time = millis();
// increment wave id (will overflow from 255 to 0)
send.setOpcode(0);
send.setWave(++wave_id);
send.setDist(0);
send.setSender(42);
screen.clear();
screen.printfn(1, "dsc[%3d] %3d / %3d", send.getSender(), send.getDist(), send.getWave());
if( xbee.broadcast(send) == XBWSEND_OK ) screen.printfn(1, "sent");
else screen.printfn(1, "failed");
}
/* [2] Listen for incoming data */
if( xbee.receive(recv) != XBWRECV_OK )
return;
uint8_t opcode = recv.getOpcode();
// ignore DISCOVER requests
if( opcode == 0 )
return;
// log message
screen.clear();
screen.print("+ wave");
screen.print(wave_id+1);
// increment wave id (will overflow from 255 to 0)
send.setOpcode(0);
send.setWave(++wave_id);
send.setDist(0);
send.setSender(42);
if( xbee.broadcast(send) == XBWSEND_OK )
Serial.println("sent");
else
Serial.println("failed");
screen.printfn(0, "msg[%3d/%3d] %3d", recv.getDist(), recv.getTTL(), recv.getSize());
screen.printfn_overflow(1, "%s", recv.getData());
}

View File

@ -4,7 +4,7 @@
XBeeWrapper::XBeeWrapper(){ xbee = XBee(); };
void XBeeWrapper::begin(unsigned long baud){
void XBeeWrapper::begin(const unsigned long baud){
xbee.setSerial(Serial1);
Serial1.begin(baud);
};

View File

@ -23,7 +23,7 @@
XBeeWrapper();
// initialises the XBee interface
void begin(unsigned long baud);
void begin(const unsigned long baud);
// tries to extract a received packet
uint8_t receive(Packet& pkt);