27 #include <libopencm3/stm32/i2c.h> 41 #define BUSVOODOO_I2C I2C2 45 static enum busvoodoo_i2c_setting_t { 46 BUSVOODOO_I2C_SETTING_NONE,
47 BUSVOODOO_I2C_SETTING_SPEED,
48 BUSVOODOO_I2C_SETTING_ADDRESSBITS,
49 BUSVOODOO_I2C_SETTING_PULLUP,
50 BUSVOODOO_I2C_SETTING_DONE,
66 bool complete =
false;
71 case BUSVOODOO_I2C_SETTING_NONE:
76 case BUSVOODOO_I2C_SETTING_SPEED:
77 if (NULL==line || 0==strlen(line)) {
80 uint32_t speed = atoi(line);
81 if (speed>0 && speed<=400) {
91 case BUSVOODOO_I2C_SETTING_ADDRESSBITS:
92 if (NULL==line || 0==strlen(line)) {
95 uint8_t addressbits = atoi(line);
96 if (7==addressbits || 10==addressbits) {
102 printf(
"1) open-drain, with embedded pull-up resistors (2kO)\n");
103 printf(
"2) open-drain, with external pull-up resistors\n");
108 case BUSVOODOO_I2C_SETTING_PULLUP:
109 if (NULL==line || 0==strlen(line)) {
111 }
else if (1==strlen(line)) {
112 uint8_t drive = atoi(line);
113 if (1==drive || 2==drive) {
122 printf(
"use LV to set pull-up voltage\n");
128 const char* pinout_io[10] = {
"GND",
"5V",
"3V3",
"LV",
"SDA",
"SCL", NULL, NULL};
133 const char* pinout_rscan[5] = {
"HV", NULL, NULL, NULL, NULL};
143 case BUSVOODOO_I2C_SETTING_DONE:
171 printf(
"slave not selected");
174 printf(
"slave not ready");
177 printf(
"not in receive mode");
180 printf(
"error detected on bus (reset I2C peripheral to correct)");
193 printf(
"write 0x%02x: ", data);
203 printf(
"slave not selected");
206 printf(
"slave not ready");
209 printf(
"not in transmit mode");
212 printf(
"error detected on bus (reset I2C peripheral to correct)");
232 printf(
" to %s: ", write ?
"write" :
"read");
242 printf(
"can't become master");
245 printf(
"not in receive mode");
248 printf(
"not in transmit mode");
251 printf(
"error detected on bus (reset I2C peripheral to correct)");
267 uint32_t length = strlen(action);
268 if (NULL==action || 0==length) {
272 if (1==length &&
'r'==action[0]) {
276 for (uint32_t i=0; i<repetition; i++) {
279 }
else if (1==length &&
'['==action[0]) {
283 printf(
"send start condition: ");
284 for (uint32_t i=0; i<repetition; i++) {
289 }
else if (1==length &&
']'==action[0]) {
293 printf(
"send stop condition: ");
294 for (uint32_t i=0; i<repetition; i++) {
299 }
else if (1==length &&
'u'==action[0]) {
303 printf(
"wait for %u us\n", repetition);
305 }
else if (1==length &&
'm'==action[0]) {
309 printf(
"wait for %u ms\n", repetition);
311 }
else if (
'0'==action[0]) {
316 for (uint32_t i=0; i<repetition; i++) {
319 }
else if (
'x'==action[1] ||
'b'==action[1]) {
321 }
else if (action[1]>=
'0' && action[1]<=
'9') {
323 }
else if (
'r'==action[1] && 2==length) {
325 }
else if (
'w'==action[1] && 2==length) {
330 }
else if (
'x'==action[0] && length>1) {
331 for (uint32_t i=1; i<length; i++) {
332 if (!((action[i]>=
'0' && action[i]<=
'9') || (action[i]>=
'a' && action[i]<=
'f') || (action[i]>=
'A' && action[i]<=
'F') || (
'r'==action[i] && i==length-1) || (
'w'==action[i] && i==length-1))) {
339 uint32_t value = strtol(&action[1], NULL, 16);
340 for (uint32_t i=0; i<repetition; i++) {
341 if (
'r'==action[length-1]) {
343 }
else if (
'w'==action[length-1]) {
349 }
else if (
'b'==action[0] && length>1) {
350 for (uint32_t i=1; i<length; i++) {
351 if (!(
'0'==action[i] ||
'1'==action[i] || (
'r'==action[i] && i==length-1) || (
'w'==action[i] && i==length-1))) {
358 uint32_t value = strtol(&action[1], NULL, 2);
359 for (uint32_t i=0; i<repetition; i++) {
360 if (
'r'==action[length-1]) {
362 }
else if (
'w'==action[length-1]) {
368 }
else if (action[0]>=
'1' && action[0]<=
'9') {
369 for (uint32_t i=1; i<length; i++) {
370 if (!((action[i]>=
'0' && action[i]<=
'9') || (
'w'==action[i] && i==length-1))) {
377 uint32_t value = strtol(&action[0], NULL, 10);
378 for (uint32_t i=0; i<repetition; i++) {
379 if (
'r'==action[length-1]) {
381 }
else if (
'w'==action[length-1]) {
387 }
else if (length>=2 && (
'"'==action[0] ||
'\''==action[0]) && (action[length-1]==action[0])) {
391 for (uint32_t r=0; r<repetition; r++) {
392 for (uint32_t i=1; i<length-1; i++) {
412 printf(
"I2C peripheral reset\n");
421 if (NULL==argument || 0==strlen(argument)) {
422 printf(
"available actions (separated by space or ,):\n");
423 printf(
"[/]\tsend start/stop conditions\n");
424 printf(
"0x0r\tselect slave with I2C address to read\n");
425 printf(
"0x0w\tselect slave with I2C address to write\n");
426 printf(
"0\twrite decimal value\n");
427 printf(
"0x0\twrite hexadecimal value\n");
428 printf(
"0b0\twrite binary value\n");
429 printf(
"\"a\"/'a'\twrite ASCII characters\n");
430 printf(
"r\tread value\n");
431 printf(
"u/m\twait 1 us/ms\n");
432 printf(
":n\trepeat action n times\n");
436 char* copy = calloc(strlen(argument)+1,
sizeof(
char));
440 strncpy(copy, argument, strlen(argument)+1);
443 printf(
"malformed action(s)\n");
457 printf(
"SCL or/and SDA are low. The signals need to be pulled up\n");
459 printf(
"set pull-up voltage with LV\n");
466 printf(
"scanning for I2C slaves\n");
467 int16_t i2c_slaves = 0;
469 printf(
"I2C slaves found: ");
479 printf(
"start condition failed\n");
484 printf(
"start condition failed\n");
490 printf(
"error detected on bus\n");
494 printf(
"error occurred\n");
500 if (-1==i2c_slaves) {
502 }
else if (-2==i2c_slaves) {
509 printf(
"stop condition failed\n");
518 printf(
"%u slave(s) found\n", i2c_slaves);
527 .command_description =
"reset I2C peripheral",
529 .argument_description = NULL,
535 .command_description =
"perform protocol actions",
537 .argument_description =
"[actions]",
543 .command_description =
"scan for slave devices",
545 .argument_description = NULL,
552 .description =
"Inter-Integrated Circuit",
library to communicate using I2C as master (API)
enum i2c_master_rc i2c_master_stop(uint32_t i2c)
sent stop condition
#define BUSVOODOO_LED_PULSE
recommended duration in ms for pulsing LEDs to show activity
static void busvoodoo_i2c_command_reset(void *argument)
command to reset I2C peripheral
BusVoodoo global definitions and methods (API)
enum i2c_master_rc i2c_master_select_slave(uint32_t i2c, uint16_t slave, bool address_10bit, bool write)
select I2C slave device
static void busvoodoo_i2c_write(uint8_t data)
write to I2C
void busvoodoo_oled_text_pinout(const char *pins[10], bool io_connector)
draw pin names on bottom (blue) part in display buffer
const char * name
name of the mode (i.e.
enum i2c_master_rc i2c_master_read(uint32_t i2c, uint8_t *data, size_t data_size)
read data over I2C
void busvoodoo_led_blue_pulse(uint32_t ms)
pulse blue LED for short duration
void i2c_master_reset(uint32_t i2c)
reset I2C peripheral, fixing any locked state
an error on the I2C bus occurred
enum i2c_master_rc i2c_master_start(uint32_t i2c)
send start condition
void busvoodoo_oled_update(void)
update OLED display RAM with current display buffer
uint16_t busvoodoo_i2c_speed
I2C speed (in kHz)
const char * busvoodoo_global_pinout_rscan[5]
RS/CAN connector pinout.
global definitions and methods (API)
static void busvoodoo_i2c_exit(void)
exit I2C mode
void sleep_us(uint32_t duration)
go to sleep for some microseconds
bool busvoodoo_full
is the BusVoodoo board fully populated (with HV voltage regulator, RS-232, RS-485, CAN transceiver on the back side)
static void busvoodoo_i2c_select(uint16_t slave, bool write)
select I2C slave
void busvoodoo_led_blue_off(void)
switch off blue LED
enum i2c_master_rc i2c_master_write(uint32_t i2c, const uint8_t *data, size_t data_size)
write data over I2C
a start or stop condition is already in progress
#define BUSVOODOO_I2C
I2C peripheral.
bool busvoodoo_i2c_embedded_pullup
if embedded or external pull-up resistors are use
void i2c_master_setup(uint32_t i2c, uint16_t frequency)
setup I2C peripheral
char shortcut
short command code (0 if not available)
void busvoodoo_leds_blink(double period, double duty)
set LED blinking pattern
void i2c_master_release(uint32_t i2c)
release I2C peripheral
const char * busvoodoo_global_pinout_io[10]
I/O connector pinout.
static bool busvoodoo_i2c_setup(char **prefix, const char *line)
setup I2C mode
char busvoodoo_global_string[64]
shared string buffer, i.e.
static const struct menu_command_t busvoodoo_i2c_commands[]
I2C menu commands.
size_t snprintf(char *str, size_t size, const char *format,...)
print format string on string or user output
bool busvoodoo_global_actions(char *actions, bool perform, bool(*action_handler)(const char *action, uint32_t repetition, bool perform))
parse and perform actions
static bool busvoodoo_i2c_action(const char *action, uint32_t repetition, bool perform)
perform I2C action
void sleep_ms(uint32_t duration)
go to sleep for some milliseconds
size_t printf(const char *format,...)
print format string on user output
slave is not read (previous operations has been nacked)
printing utilities to replace the large printf from the standard library (API)
void busvoodoo_oled_text_left(char *text)
draw mode text on top (yellow) left side in display buffer
float busvoodoo_embedded_pullup(bool on)
enable embedded pull-up resistors
static void busvoodoo_i2c_read(void)
read from I2C
#define LENGTH(x)
get the length of an array
bool i2c_master_check_signals(uint32_t i2c)
check if SDA and SCL signals are high
const struct busvoodoo_mode_t busvoodoo_i2c_mode
I2C mode interface definition.
library to show BusVoodoo mode information on SSD1306 OLED display: name, activity, pinout (API)
static enum busvoodoo_i2c_setting_t busvoodoo_i2c_setting
current mode setup stage
BusVoodoo mode interface.
static void busvoodoo_i2c_command_actions(void *argument)
command to perform actions
uint8_t busvoodoo_i2c_addressbits
I2C address bits (7 or 10)
static void busvoodoo_i2c_command_scan(void *argument)
command to scan for slave devices