27 #include <libopencm3/stm32/gpio.h> 28 #include <libopencm3/stm32/rcc.h> 29 #include <libopencm3/stm32/spi.h> 42 #define BUSVOODOO_SPI_ID 2 46 static enum busvoodoo_spi_setting_t { 47 BUSVOODOO_SPI_SETTING_NONE,
48 BUSVOODOO_SPI_SETTING_DUPLEX,
49 BUSVOODOO_SPI_SETTING_FREQUENCY,
50 BUSVOODOO_SPI_SETTING_DATABITS,
51 BUSVOODOO_SPI_SETTING_BITORDER,
52 BUSVOODOO_SPI_SETTING_MODE,
53 BUSVOODOO_SPI_SETTING_DRIVE,
54 BUSVOODOO_SPI_SETTING_DONE,
78 bool complete =
false;
83 case BUSVOODOO_SPI_SETTING_NONE:
85 printf(
"1) full-duplex\n");
86 printf(
"2) bidirectional\n");
90 case BUSVOODOO_SPI_SETTING_DUPLEX:
91 if (NULL==line || 0==strlen(line)) {
93 }
else if (1==strlen(line)) {
94 uint8_t duplex = atoi(line);
95 if (1==duplex || 2==duplex) {
102 for (uint8_t div=0; div<8; div++) {
103 printf(
"%u) %u kHz\n", div+1, 36000/(2<<div));
109 case BUSVOODOO_SPI_SETTING_FREQUENCY:
110 if (NULL==line || 0==strlen(line)) {
112 }
else if (1==strlen(line)) {
113 uint8_t baudrate = atoi(line);
114 if (baudrate>0 && baudrate<=9) {
124 case BUSVOODOO_SPI_SETTING_DATABITS:
125 if (NULL==line || 0==strlen(line)) {
127 }
else if (1==strlen(line) || 2==strlen(line)) {
128 uint8_t databits = atoi(line);
129 if (8==databits || 16==databits) {
135 printf(
"1) most significant bit first\n");
136 printf(
"2) least significant bit first\n");
141 case BUSVOODOO_SPI_SETTING_BITORDER:
142 if (NULL==line || 0==strlen(line)) {
144 }
else if (1==strlen(line)) {
145 uint8_t bitorder = atoi(line);
146 if (1==bitorder || 2==bitorder) {
152 printf(
"1) mode 0 (clock polarity: idle low, clock phase: sample data on rising edge)\n");
153 printf(
"2) mode 1 (clock polarity: idle low, clock phase: sample data on falling edge)\n");
154 printf(
"3) mode 2 (clock polarity: idle high, clock phase: sample data on falling edge)\n");
155 printf(
"4) mode 3 (clock polarity: idle high, clock phase: sample data on rising edge)\n");
160 case BUSVOODOO_SPI_SETTING_MODE:
161 if (NULL==line || 0==strlen(line)) {
163 }
else if (1==strlen(line)) {
164 uint8_t mode = atoi(line);
165 if (mode>=1 && mode<=4) {
171 printf(
"1) push-pull (3.3V)\n");
172 printf(
"2) open-drain, with embedded pull-up resistors (2kO)\n");
173 printf(
"3) open-drain, with external pull-up resistors\n");
178 case BUSVOODOO_SPI_SETTING_DRIVE:
179 if (NULL==line || 0==strlen(line)) {
181 }
else if (1==strlen(line)) {
182 uint8_t drive = atoi(line);
183 if (1==drive || 2==drive || 3==drive) {
190 rcc_periph_clock_enable(RCC_AFIO);
241 printf(
"use LV to set pull-up voltage\n");
247 const char* pinout_io[10] = {
"GND",
"5V",
"3V3",
"LV", NULL, NULL,
"MISO",
"SCK",
"MOSI",
"SS"};
250 pinout_io[8] =
"MOSIMISO";
256 const char* pinout_rscan[5] = {
"HV", NULL, NULL, NULL, NULL};
279 printf(
"write: 0x%02x\n", (uint8_t)value);
281 printf(
"write: 0x%04x\n", value);
291 printf(
"read: 0x%02x\n", (uint8_t)value);
293 printf(
"read: 0x%04x\n", value);
312 printf(
"read: 0x%02x\n", (uint8_t)value);
314 printf(
"read: 0x%04x\n", value);
346 uint32_t length = strlen(action);
347 if (NULL==action || 0==length) {
351 if (1==length &&
'r'==action[0]) {
355 for (uint32_t i=0; i<repetition; i++) {
358 }
else if (1==length &&
'['==action[0]) {
365 }
else if (1==length &&
']'==action[0]) {
369 printf(
"de-select slave\n");
372 }
else if (1==length &&
'u'==action[0]) {
376 printf(
"wait for %u us\n", repetition);
378 }
else if (1==length &&
'm'==action[0]) {
382 printf(
"wait for %u ms\n", repetition);
384 }
else if (
'0'==action[0]) {
389 for (uint32_t i=0; i<repetition; i++) {
392 }
else if (
'x'==action[1] ||
'b'==action[1]) {
394 }
else if (action[1]>=
'0' && action[1]<=
'9') {
399 }
else if (
'x'==action[0] && length>1) {
400 for (uint32_t i=1; i<length; i++) {
401 if (!((action[i]>=
'0' && action[i]<=
'9') || (action[i]>=
'a' && action[i]<=
'f') || (action[i]>=
'A' && action[i]<=
'F'))) {
408 uint32_t value = strtol(&action[1], NULL, 16);
409 for (uint32_t i=0; i<repetition; i++) {
412 }
else if (
'b'==action[0] && length>1) {
413 for (uint32_t i=1; i<length; i++) {
414 if (action[i]<
'0' || action[i]>
'1') {
421 uint32_t value = strtol(&action[1], NULL, 2);
422 for (uint32_t i=0; i<repetition; i++) {
425 }
else if (action[0]>=
'1' && action[0]<=
'9') {
426 for (uint32_t i=1; i<length; i++) {
427 if (action[i]<
'0' || action[i]>
'9') {
434 uint32_t value = strtol(&action[0], NULL, 10);
435 for (uint32_t i=0; i<repetition; i++) {
438 }
else if (length>=2 && (
'"'==action[0] ||
'\''==action[0]) && (action[length-1]==action[0])) {
442 for (uint32_t r=0; r<repetition; r++) {
443 for (uint32_t i=1; i<length-1; i++) {
460 if (NULL==argument || 0==strlen(argument)) {
461 printf(
"available actions (separated by space or ,):\n");
462 printf(
"[/]\tselect/deselect slave\n");
463 printf(
"0\twrite decimal value\n");
464 printf(
"0x0\twrite hexadecimal value\n");
465 printf(
"0b0\twrite binary value\n");
466 printf(
"\"a\"/'a'\twrite ASCII characters\n");
467 printf(
"r\tread value\n");
468 printf(
"u/m\twait 1 us/ms\n");
469 printf(
":n\trepeat action n times\n");
473 char* copy = calloc(strlen(argument)+1,
sizeof(
char));
477 strncpy(copy, argument, strlen(argument)+1);
480 printf(
"malformed action(s)\n");
492 .command_description =
"perform protocol actions",
494 .argument_description =
"[actions]",
501 .description =
"Serial Peripheral Interface",
#define BUSVOODOO_SPI_ID
SPI peripheral.
#define SPI_MOSI_PORT(x)
get SPI port for MOSI signal based on SPI identifier
#define BUSVOODOO_LED_PULSE
recommended duration in ms for pulsing LEDs to show activity
BusVoodoo global definitions and methods (API)
static bool busvoodoo_spi_setup(char **prefix, const char *line)
setup SPI mode
static void busvoodoo_spi_command_actions(void *argument)
command to perform actions
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.
void busvoodoo_led_blue_pulse(uint32_t ms)
pulse blue LED for short duration
static bool busvoodoo_spi_drive
pin drive mode (true = push-pull, false = open-drain)
static enum busvoodoo_spi_setting_t busvoodoo_spi_setting
current mode setup stage
#define SPI_NSS_PORT(x)
get SPI port for NSS signal based on SPI identifier
void busvoodoo_oled_update(void)
update OLED display RAM with current display buffer
#define SPI_MOSI_PIN(x)
get SPI pin for MOSI signal based on SPI identifier
const char * busvoodoo_global_pinout_rscan[5]
RS/CAN connector pinout.
static bool busvoodoo_spi_action(const char *action, uint32_t repetition, bool perform)
perform SPI action
const struct busvoodoo_mode_t busvoodoo_spi_mode
SPI mode interface definition.
global definitions and methods (API)
void sleep_us(uint32_t duration)
go to sleep for some microseconds
#define RCC_SPI_MISO_PORT(x)
get RCC for GPIO port for SPI MISO signals
static bool busvoodoo_spi_pullup
if embedded pull-up resistors are used
#define RCC_SPI_MOSI_PORT(x)
get RCC for GPIO port for SPI MOSI signals
static uint8_t busvoodoo_spi_standard_mode
SPI mode (defining clock polarity and phase)
bool busvoodoo_full
is the BusVoodoo board fully populated (with HV voltage regulator, RS-232, RS-485, CAN transceiver on the back side)
#define RCC_SPI(x)
get RCC for SPI based on SPI identifier
void busvoodoo_led_blue_off(void)
switch off blue LED
#define SPI_NSS_PIN(x)
get SPI pin for NSS signal based on SPI identifier
static uint8_t busvoodoo_spi_baudrate
SPI baud rate (corresponding to baud rate control, e.g.
static void busvoodoo_spi_exit(void)
exit SPI mode
#define SPI_SCK_PORT(x)
get SPI port for SCK signal based on SPI identifier
char shortcut
short command code (0 if not available)
const char * busvoodoo_global_pinout_io[10]
I/O connector pinout.
char busvoodoo_global_string[64]
shared string buffer, i.e.
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
void sleep_ms(uint32_t duration)
go to sleep for some milliseconds
#define SPI_MISO_PORT(x)
get SPI port for MISO signal based on SPI identifier
static void busvoodoo_spi_write(uint16_t value)
write to SPI
size_t printf(const char *format,...)
print format string on user output
#define SPI(x)
get SPI based on SPI identifier
printing utilities to replace the large printf from the standard library (API)
#define RCC_SPI_SCK_PORT(x)
get RCC for GPIO port for SPI SCK signals
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
#define LENGTH(x)
get the length of an array
static const struct menu_command_t busvoodoo_spi_commands[]
SPI menu commands.
static uint8_t busvoodoo_spi_databits
SPI data frame bit width (8 or 16)
static bool busvoodoo_spi_duplex
SPI duplex mode (true = full-duplex, false = bidirectional)
#define SPI_MISO_PIN(x)
get SPI pin for MISO signal based on SPI identifier
library to show BusVoodoo mode information on SSD1306 OLED display: name, activity, pinout (API)
static void busvoodoo_spi_read(void)
read from SPI
static bool busvoodoo_spi_bitorder
SPI data frame bit order (true = MSb first, false = LSb first)
#define RCC_SPI_NSS_PORT(x)
get RCC for GPIO port for SPI NSS signals
BusVoodoo mode interface.
#define SPI_SCK_PIN(x)
get SPI pin for SCK signal based on SPI identifier