From 750a6d3966925482bd17f6ba6d77e28bba636601 Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Fri, 3 May 2013 21:57:37 +0200 Subject: digital/lcd/src: reply to I2C commands --- digital/lcd/src/Makefile | 2 +- digital/lcd/src/main.cc | 86 +++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 78 insertions(+), 10 deletions(-) (limited to 'digital/lcd') diff --git a/digital/lcd/src/Makefile b/digital/lcd/src/Makefile index f6926f6d..e641922b 100644 --- a/digital/lcd/src/Makefile +++ b/digital/lcd/src/Makefile @@ -4,6 +4,6 @@ TARGETS = stm32f4 stm32f4_PROGS = lcd lcd_SOURCES = lcd.cc main.cc -MODULES = hal/gpio utils +MODULES = hal/gpio hal/i2c utils include $(BASE)/build/top.mk diff --git a/digital/lcd/src/main.cc b/digital/lcd/src/main.cc index ec7441b1..38016cd2 100644 --- a/digital/lcd/src/main.cc +++ b/digital/lcd/src/main.cc @@ -27,21 +27,89 @@ #include "ucoolib/utils/delay.hh" #include +#include "ucoolib/hal/i2c/i2c.hh" +#include "ucoolib/utils/crc.hh" + +static const int i2c_status_size = 3; +static const int i2c_command_size = 16; + +static uint8_t i2c_seq; + +/// Handle a command received by I2C. +void +i2c_handle (LCD &lcd, const char *buf, int size) +{ + // Command too small. + if (size < 3) + return; + // Check CRC. + if (ucoo::crc8_compute ((const uint8_t *) buf + 1, size - 1) != buf[0]) + return; + // Handle sequence number. + if (buf[1] == 0) + // Transient command, not handled for the moment. + return; + if (buf[1] == i2c_seq) + // Duplicated command. + return; + // OK, now handle command. + char cmd = buf[2]; + const char *arg = &buf[3]; + int arg_nb = size - 3; + switch (cmd) + { + case 'c': + // Team color. + if (arg_nb != 3) + return; + lcd.clear (LCD::color (arg[0], arg[1], arg[2])); + break; + default: + // Unknown command. + return; + } + // Acknowledge. + i2c_seq = buf[1]; +} + +/// Poll I2C interface for commands and update status. +void +i2c_poll (LCD &lcd, ucoo::I2cSlaveDataBuffer &i2c_data) +{ + char buf[i2c_command_size]; + int size; + // Handle incoming commands. + while ((size = i2c_data.poll (buf, sizeof (buf)))) + i2c_handle (lcd, buf, size); + // Update status. + char status[i2c_status_size]; + status[1] = i2c_seq; + status[2] = 0; + status[0] = ucoo::crc8_compute ((const uint8_t *) &status[1], + sizeof (status) - 1); + i2c_data.update (status, sizeof (status)); +} + int main (int argc, const char **argv) { ucoo::arch_init (argc, argv); rcc_peripheral_enable_clock (&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN | RCC_AHB1ENR_IOPBEN | RCC_AHB1ENR_IOPCEN); + // I2C: B8: SCL, B9: SDA + gpio_mode_setup (GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO8 | GPIO9); + gpio_set_output_options (GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_2MHZ, GPIO8 | GPIO9); + gpio_set_af (GPIOB, GPIO_AF4, GPIO8 | GPIO9); + ucoo::I2cHard i2c (0); + i2c.enable (); + ucoo::I2cSlaveDataBufferSize i2c_data; + i2c.register_data (0x20, i2c_data); + // Init. LCD lcd; - ucoo::delay (1); - lcd.clear (LCD::color (255, 0, 0)); - ucoo::delay (1); - lcd.clear (LCD::color (0, 255, 0)); - ucoo::delay (1); - lcd.clear (LCD::color (0, 0, 255)); - ucoo::delay (1); - lcd.rainbow (); + // Wait orders. while (1) - ; + { + i2c_poll (lcd, i2c_data); + ucoo::delay_ms (1); + } } -- cgit v1.2.3