summaryrefslogtreecommitdiffhomepage
path: root/digital
diff options
context:
space:
mode:
authorNicolas Schodet2013-05-03 21:57:37 +0200
committerNicolas Schodet2013-05-03 22:46:11 +0200
commit750a6d3966925482bd17f6ba6d77e28bba636601 (patch)
tree7dd768f9b953e2e485994dc3f9ea725ec22d2ff0 /digital
parent1c4f7b6044bb8880886ba4d8bd578d689430377e (diff)
digital/lcd/src: reply to I2C commands
Diffstat (limited to 'digital')
-rw-r--r--digital/lcd/src/Makefile2
-rw-r--r--digital/lcd/src/main.cc86
2 files changed, 78 insertions, 10 deletions
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 <libopencm3/stm32/f4/rcc.h>
+#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_status_size, i2c_command_size> 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);
+ }
}