CuVoodoo STM32F1 firmware template
busvoodoo_global.c
Go to the documentation of this file.
1 /* This program is free software: you can redistribute it and/or modify
2  * it under the terms of the GNU General Public License as published by
3  * the Free Software Foundation, either version 3 of the License, or
4  * (at your option) any later version.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9  * GNU General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public License
12  * along with this program. If not, see <http://www.gnu.org/licenses/>.
13  *
14  */
22 /* standard libraries */
23 #include <stdint.h> // standard integer types
24 #include <stdlib.h> // standard utilities
25 #include <string.h> // string utilities
26 #include <math.h> // math utilities
27 
28 /* STM32 (including CM3) libraries */
29 #include <libopencm3/cm3/nvic.h> // interrupt handler
30 #include <libopencm3/stm32/gpio.h> // general purpose input output library
31 #include <libopencm3/stm32/rcc.h> // real-time control clock library
32 #include <libopencm3/stm32/adc.h> // ADC utilities
33 #include <libopencm3/stm32/dac.h> // DAC utilities
34 #include <libopencm3/stm32/timer.h> // timer utilities
35 
36 /* own libraries */
37 #include "global.h" // board definitions
38 #include "menu.h" // command definitions
39 #include "print.h" // print utilities
40 #include "busvoodoo_global.h" // BusVoodoo definitions
41 
45 #define BUSVOODOO_LED_TIMER 5
49 static volatile bool busvoodoo_global_led_blue = false;
50 
51 static volatile bool busvoodoo_global_led_red = false;
52 
54 static const float busvoodoo_version_voltages[] = {100.0/(10.0+100.0)*3.3}; // version A start with revision 27
55 
56 const char* busvoodoo_global_pinout_io[10] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
57 const char* busvoodoo_global_pinout_rscan[5] = {NULL, NULL, NULL, NULL, NULL};
58 
59 const char* busvoodoo_io_names[13] = {"I2C_SMBA/SPI_NSS/I2S_WS/UART1_CK", "SDIO_CMD", "UART1_CTS/SPI_SCK/I2S_CK", "SDIO_D3/UART2_RX", "I2C_SDA/UART1_RX", "SDIO_D0", "SPI_MOSI/I2S_SD", "SDIO_CK", "I2C_SCL/UART1_TX", "SDIO_D1", "I2S_MCK", "UART1_RTS/SPI_MISO", "SDIO_D2/UART2_TX"};
60 const uint32_t busvoodoo_io_ports[13] = {GPIOB, GPIOD, GPIOB, GPIOC, GPIOB, GPIOC, GPIOB, GPIOC, GPIOB, GPIOC, GPIOC, GPIOB, GPIOC};
61 const uint32_t busvoodoo_io_pins[13] = {GPIO12, GPIO2, GPIO13, GPIO11, GPIO11, GPIO8, GPIO15, GPIO12, GPIO10, GPIO9, GPIO6, GPIO14, GPIO10};
62 const uint8_t busvoodoo_io_groups[13] = {6, 6, 4, 4, 1, 1, 5, 5, 2, 2, 3, 3, 3};
63 
64 bool busvoodoo_full = false;
65 char busvoodoo_version = '0';
67 
68 void busvoodoo_setup(void)
69 {
70  // enable all GPIO domains since we use pins on all ports
71  rcc_periph_clock_enable(RCC_GPIOA); // enable clock for all GPIO domains
72  rcc_periph_clock_enable(RCC_GPIOB); // enable clock for all GPIO domains
73  rcc_periph_clock_enable(RCC_GPIOC); // enable clock for all GPIO domains
74  rcc_periph_clock_enable(RCC_GPIOD); // enable clock for all GPIO domains
75  rcc_periph_clock_enable(RCC_AFIO); // enable clock for alternate function (for communication)
76  busvoodoo_safe_state(); // put pins in safe state (for common light version)
77 
78  // check if this BusVoodoo is a full flavor
79  rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_HV_CHANNEL)); // enable clock for GPIO domain for HV channel
81  gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_HV_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, ADC12_IN_PIN(BUSVOODOO_HV_CHANNEL)); // set HV channel as digital input with pull-up capabilities
82  // on a full version (fully populated board) the ADC HV signal will be pulled low
83  if (gpio_get(ADC12_IN_PORT(BUSVOODOO_HV_CHANNEL), ADC12_IN_PIN(BUSVOODOO_HV_CHANNEL))) { // check is ADC HV is pulled low
84  busvoodoo_full = false;
85  } else {
86  busvoodoo_full = true;
87  busvoodoo_safe_state(); // also put the full version pins in safe state
88  }
89 
90  // setup ADC to measure the 5V, 3.3V, LV, and HV power rails voltages, and hardware version channel
91  rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_5V_CHANNEL)); // enable clock for GPIO domain for 5V channel
92  gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_5V_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_5V_CHANNEL)); // set 5V channel as analogue input for the ADC
93  rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_3V3_CHANNEL)); // enable clock for GPIO domain for 3.3V channel
94  gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_3V3_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_3V3_CHANNEL)); // set 3.3V channel as analogue input for the ADC
95  rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_LV_CHANNEL)); // enable clock for GPIO domain for LV channel
96  gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_LV_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_LV_CHANNEL)); // set LV channel as analogue input for the ADC
97  rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_HV_CHANNEL)); // enable clock for GPIO domain for HV channel
98  gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_HV_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_HV_CHANNEL)); // set HV channel as analogue input for the ADC
99  rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_HW_VERSION_CHANNEL)); // enable clock for GPIO domain for hardware version channel
100  gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_HW_VERSION_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_HW_VERSION_CHANNEL)); // set hardware version channel as analogue input for the ADC
101  rcc_periph_clock_enable(RCC_ADC1); // enable clock for ADC domain
102  adc_off(ADC1); // switch off ADC while configuring it
103  adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC); // use 28.5 cycles to sample (long enough to be stable)
104  adc_enable_temperature_sensor(ADC1); // enable internal voltage reference
105  adc_enable_external_trigger_regular(ADC1, ADC_CR2_EXTSEL_SWSTART); // use software trigger to start conversion
106  adc_set_single_conversion_mode(ADC1); // we only convert one channel after another
107  adc_power_on(ADC1); // switch on ADC
108  sleep_us(1); // wait t_stab for the ADC to stabilize
109  adc_reset_calibration(ADC1); // remove previous non-calibration
110  adc_calibration(ADC1); // calibrate ADC for less accuracy errors
111 
112  // find out version of the board
113  gpio_set_mode(GPIO(BUSVOODOO_HW_VERSION_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO(BUSVOODOO_HW_VERSION_PIN)); // use pull up and down to check if a voltage divider is present on the pin
115  bool version_up = (0!=gpio_get(GPIO(BUSVOODOO_HW_VERSION_PORT), GPIO(BUSVOODOO_HW_VERSION_PIN))); // check if the signal is still up
116  gpio_clear(GPIO(BUSVOODOO_HW_VERSION_PORT), GPIO(BUSVOODOO_HW_VERSION_PIN)); // pull down
117  bool version_down = (0==gpio_get(GPIO(BUSVOODOO_HW_VERSION_PORT), GPIO(BUSVOODOO_HW_VERSION_PIN))); // check if the signal is still down
118  gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_HW_VERSION_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_HW_VERSION_CHANNEL)); // put back to analog input
119  // get version
120  if (version_up && version_down) { // no voltage divider on pin
121  busvoodoo_version = '0'; // the pin is floating only for version 0 (= revision 18)
122  } else { // voltage divider on pin
123  float version_voltage = busvoodoo_vreg_get(BUSVOODOO_HW_VERSION_CHANNEL); // measure hardware version voltage
124  for (uint8_t i=0; i<LENGTH(busvoodoo_version_voltages); i++) { // go through expected version voltages
125  if (version_voltage>busvoodoo_version_voltages[i]-0.2 && version_voltage<busvoodoo_version_voltages[i]+0.2) { // verify if voltage matches
126  busvoodoo_version = 'A'+i; // remember version name for matching voltage
127  break; // stop searching
128  }
129  }
130  }
131 
132  // setup DAC to control LV and HV voltage outputs
133  gpio_set_mode(GPIO(BUSVOODOO_LVCTL_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO(BUSVOODOO_LVCTL_PIN)); // set LV pin as analog (the DAC will use it as output)
134  rcc_periph_clock_enable(RCC_DAC); // enable clock for DAC domain
135  dac_disable(BUSVOODOO_LVCTL_CHANNEL); // disable output to configure it properly
136  dac_buffer_enable(BUSVOODOO_LVCTL_CHANNEL); // enable output buffer to be able to drive larger loads (should be per default)
137  if (busvoodoo_full) {
138  gpio_set_mode(GPIO(BUSVOODOO_HVCTL_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO(BUSVOODOO_HVCTL_PIN)); // set HV pin as analog (the DAC will use it as output)
139  dac_disable(BUSVOODOO_HVCTL_CHANNEL); // disable output to configure it properly
140  dac_buffer_enable(BUSVOODOO_HVCTL_CHANNEL); // enable output buffer to be able to drive larger loads (should be per default)
141  }
142  dac_set_trigger_source(DAC_CR_TSEL1_SW); // use software to trigger the voltage change
143  dac_set_trigger_source(DAC_CR_TSEL2_SW); // use software to trigger the voltage change
144 
145  // enable timer for LED blinking
146  rcc_periph_clock_enable(RCC_TIM(BUSVOODOO_LED_TIMER)); // enable clock for timer domain
147  timer_reset(TIM(BUSVOODOO_LED_TIMER)); // reset timer configuration
148  timer_set_mode(TIM(BUSVOODOO_LED_TIMER), TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); // configure timer to up counting mode
149  timer_set_prescaler(TIM(BUSVOODOO_LED_TIMER), (rcc_ahb_frequency/2000)-1); // set prescaler to have 2kHz ticks (the prescaler is not large enough for 1kHz ticks)
150  timer_set_period(TIM(BUSVOODOO_LED_TIMER), 0xffff); // set period to maximum
151  nvic_enable_irq(NVIC_TIM_IRQ(BUSVOODOO_LED_TIMER)); // enable interrupts for this timer
152 }
153 
155 {
156  // disable voltage outputs
157  gpio_set(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // disable 5V and 3.3V output on connector
158  gpio_set_mode(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(BUSVOODOO_VOUTEN_PIN)); // set pin as output (open-drain pulled high to disable the pMOS)
159  gpio_clear(GPIO(BUSVOODOO_LVEN_PORT), GPIO(BUSVOODOO_LVEN_PIN)); // disable LV voltage regulator
160  gpio_set_mode(GPIO(BUSVOODOO_LVEN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUSVOODOO_LVEN_PIN)); // set pin as output (push-pull, pulled low for safety)
161  gpio_set(GPIO(BUSVOODOO_HVEN_PORT), GPIO(BUSVOODOO_HVEN_PIN)); // disable HV voltage regulator
162  gpio_set_mode(GPIO(BUSVOODOO_HVEN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(BUSVOODOO_HVEN_PIN)); // set pin as output (open-drain pulled high to disable the pMOS)
163 
164  // set DAC channel back to analog
165  gpio_set_mode(GPIO(BUSVOODOO_LVCTL_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO(BUSVOODOO_LVCTL_PIN)); // set LV pin as analog
166  gpio_set_mode(GPIO(BUSVOODOO_HVCTL_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO(BUSVOODOO_HVCTL_PIN)); // set HV pin as analog
167 
168  // disable embedded pull-ups
169  gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON, 0); // disable JTAG (but keep SWD) so to use the underlying GPIOs (PA15, PB3, PB4)
170  gpio_set(GPIO(BUSVOODOO_5VPULLUP_PORT), GPIO(BUSVOODOO_5VPULLUP_PIN)); // set pin high to disable 5V embedded pull-up
171  gpio_set_mode(GPIO(BUSVOODOO_5VPULLUP_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(BUSVOODOO_5VPULLUP_PIN)); // set pin as output (open-drain pulled high to disable the pMOS)
172  gpio_set(GPIO(BUSVOODOO_OEPULLUP_PORT), GPIO(BUSVOODOO_OEPULLUP_PIN)); // set pin high to disable embedded pull-up bus switch
173  gpio_set_mode(GPIO(BUSVOODOO_OEPULLUP_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(BUSVOODOO_OEPULLUP_PIN)); // set pin as output (open-drain pulled high to disable the bus switch)
174 
175  // disable all signal I/O outputs
176  for (uint8_t pin=0; pin<LENGTH(busvoodoo_io_ports) && pin<LENGTH(busvoodoo_io_pins); pin++) {
177  gpio_set_mode(busvoodoo_io_ports[pin], GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, busvoodoo_io_pins[pin]); // set pin back to input (floating)
178  }
179 
180  if (busvoodoo_full) {
181  // disable RS-232 signals
182  gpio_set_mode(GPIO(BUSVOODOO_RS232_TX_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_RS232_TX_PIN)); // set pin to floating
183  gpio_set_mode(GPIO(BUSVOODOO_RS232_RX_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_RS232_RX_PIN)); // set pin to floating
184  gpio_set_mode(GPIO(BUSVOODOO_RS232_RTS_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_RS232_RTS_PIN)); // set pin to floating
185  gpio_set_mode(GPIO(BUSVOODOO_RS232_CTS_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_RS232_CTS_PIN)); // set pin to floating
186  gpio_set(GPIO(BUSVOODOO_RS232_EN_PORT), GPIO(BUSVOODOO_RS232_EN_PIN)); // set high to disable receiver
187  gpio_set_mode(GPIO(BUSVOODOO_RS232_EN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(BUSVOODOO_RS232_EN_PIN)); // use external pull-up resistor to set high by default
188  gpio_clear(GPIO(BUSVOODOO_RS232_SHDN_PORT), GPIO(BUSVOODOO_RS232_SHDN_PIN)); // set low to disable transmitter
189  gpio_set_mode(GPIO(BUSVOODOO_RS232_SHDN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUSVOODOO_RS232_SHDN_PIN)); // there is also an external pull-down resistor to disable per default
190 
191  // disable RS-485 signals (RS and TX are shared with RS-232)
192  gpio_set(GPIO(BUSVOODOO_RS485_RE_PORT), GPIO(BUSVOODOO_RS485_RE_PIN)); // set high to disable receiver
193  gpio_set_mode(GPIO(BUSVOODOO_RS485_RE_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(BUSVOODOO_RS485_RE_PIN)); // use external pull-up resistor to set high by default
194  gpio_clear(GPIO(BUSVOODOO_RS485_DE_PORT), GPIO(BUSVOODOO_RS485_DE_PIN)); // set low to disable transmitter
195  gpio_set_mode(GPIO(BUSVOODOO_RS485_DE_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUSVOODOO_RS485_DE_PIN)); // there is also an external pull-down resistor to disable per default
196  gpio_set_mode(GPIO(BUSVOODOO_RS485_TX_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_RS485_TX_PIN)); // set pin to floating
197  gpio_set_mode(GPIO(BUSVOODOO_RS485_RX_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_RS485_RX_PIN)); // set pin to floating
198 
199  // disable CAN transceiver and signals (put back to input floating)
200  gpio_set_mode(GPIO(BUSVOODOO_CAN_TX_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_CAN_TX_PIN)); // set pin to floating
201  gpio_set_mode(GPIO(BUSVOODOO_CAN_RX_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_CAN_RX_PIN)); // set pin to floating
202  gpio_set(GPIO(BUSVOODOO_CAN_EN_PORT), GPIO(BUSVOODOO_CAN_EN_PIN)); // set high to power off transceiver
203  gpio_set_mode(GPIO(BUSVOODOO_CAN_EN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(BUSVOODOO_CAN_EN_PIN)); // use external pull-up resistor to set high by default
204  }
205 }
206 
208 {
209  if (on) { // we need to switch on Vout
210  gpio_clear(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // enable Vout
211  } else {
212  gpio_set(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // disable Vout
213  }
214 
215  bool to_return = true;
216  sleep_ms(1); // wait a bit for voltage to settle
217  float voltage = busvoodoo_vreg_get(BUSVOODOO_5V_CHANNEL); // get 5V power rail voltage
218  if (voltage<4.0 || voltage>5.5) {
219  to_return = false; // voltage output is not ok
220  }
221  voltage = busvoodoo_vreg_get(BUSVOODOO_3V3_CHANNEL); // get 3.3V power rail voltage
222  if (voltage<3.0 || voltage>3.6) {
223  to_return = true; // voltage output is not ok
224  }
225  return to_return;
226 }
227 
228 float busvoodoo_vreg_get(uint8_t channel)
229 {
230  if (channel!=BUSVOODOO_5V_CHANNEL && channel!=BUSVOODOO_3V3_CHANNEL && channel!=BUSVOODOO_LV_CHANNEL && channel!=BUSVOODOO_HV_CHANNEL && channel!=BUSVOODOO_HW_VERSION_CHANNEL) { // check channel
231  return NAN;
232  }
233 
234  uint8_t channels[2] = {ADC_CHANNEL17, ADC_CHANNEL17}; // voltages to convert: internal and internal (as fallback)
235  switch (channel) { // set desired channel
237  channels[1] = ADC_CHANNEL(BUSVOODOO_5V_CHANNEL);
238  break;
240  channels[1] = ADC_CHANNEL(BUSVOODOO_3V3_CHANNEL);
241  break;
243  channels[1] = ADC_CHANNEL(BUSVOODOO_LV_CHANNEL);
244  break;
246  channels[1] = ADC_CHANNEL(BUSVOODOO_HV_CHANNEL);
247  break;
250  break;
251  default: // unknown channel
252  break;
253  }
254  adc_set_regular_sequence(ADC1, LENGTH(channels), channels); // set channels to convert
255  adc_enable_discontinuous_mode_regular(ADC1, LENGTH(channels)); // convert all channels
256  uint16_t values[LENGTH(channels)] = {0}; // to store converted values
257  ADC_SR(ADC1) = 0; // reset flags
258  adc_start_conversion_regular(ADC1); // start conversion for individual channels
259  for (uint8_t channel_i=0; channel_i<LENGTH(channels); channel_i++) { // get all conversions
260  while (!adc_eoc(ADC1)); // wait until conversion finished
261  values[channel_i] = adc_read_regular(ADC1); // read voltage value (clears flag)
262  }
263  float to_return = NAN; // voltage to return
264  switch (channel) { // get converted value and calculate according to the voltage divider on this channel
266  to_return = values[1]/(10.0/(10.0+10.0));
267  break;
269  to_return = values[1]/(10.0/(10.0+10.0));
270  break;
272  to_return = values[1]/(10.0/(10.0+10.0));
273  break;
275  to_return = values[1]/(1.5/(10.0+1.5));
276  break;
278  to_return = values[1];
279  break;
280  default: // unknown channel
281  to_return = NAN;
282  break;
283  }
284  if (!isnan(to_return)) {
285  to_return *= 1.2/values[0]; // calculate voltage from converted values using internal 1.2V voltage reference
286  }
287  return to_return;
288 }
289 
290 float busvoodoo_lv_set(float voltage)
291 {
292  float volt = NAN; // common variable for voltages
293  if (voltage<=0.3) { // disable voltage regulator
294  gpio_clear(GPIO(BUSVOODOO_LVEN_PORT), GPIO(BUSVOODOO_LVEN_PIN)); // disable LV voltage regulator
295  dac_disable(BUSVOODOO_LVCTL_CHANNEL); // disable LV control
296  } else { // enable voltage regulator
297  if (voltage>4.85) { // use the 5V directly
298  gpio_clear(GPIO(BUSVOODOO_5VPULLUP_PORT), GPIO(BUSVOODOO_5VPULLUP_PIN)); // put 5V on LV line
299  } else { // use adjustable voltage regulator (5.0V rail minus LDO and diodes)
300  gpio_set(GPIO(BUSVOODOO_5VPULLUP_PORT), GPIO(BUSVOODOO_5VPULLUP_PIN)); // disable 5V input
301  volt = busvoodoo_vreg_get(BUSVOODOO_3V3_CHANNEL); // get reference voltage
302  if (isnan(voltage)) {
303  return NAN;
304  }
305  uint16_t dac_set = BUSVOODOO_LV_SET(voltage)/volt*4095; // DAC value corresponding to the voltage
306  dac_load_data_buffer_single(dac_set, RIGHT12, BUSVOODOO_LVCTL_CHANNEL); // set output so the voltage regulator is set to 2.5V
307  dac_software_trigger(BUSVOODOO_LVCTL_CHANNEL); // transfer the value to the DAC
308  dac_enable(BUSVOODOO_LVCTL_CHANNEL); // enable DAC
309  gpio_set(GPIO(BUSVOODOO_LVEN_PORT), GPIO(BUSVOODOO_LVEN_PIN)); // enable LV voltage regulator
310  }
311  }
312  sleep_ms(50); // let voltage settle
313  volt = busvoodoo_vreg_get(BUSVOODOO_LV_CHANNEL); // get LV voltage to return
314 
315  return volt; // return measured voltage
316 }
317 
318 float busvoodoo_hv_set(float voltage)
319 {
320  if (!busvoodoo_full) { // the HV voltage regulator is only present on the full version
321  return NAN;
322  }
323 
324  float volt = NAN; // common variable for voltages
325  if (voltage<3.29) { // disable voltage regulator
326  gpio_set(GPIO(BUSVOODOO_HVEN_PORT), GPIO(BUSVOODOO_HVEN_PIN)); // disable HV voltage regulator
327  dac_disable(BUSVOODOO_HVCTL_CHANNEL); // disable HV control
328  } else {
329  if (voltage>24.0) { // enforce upper voltage limit (diodes limit is 30V, ADC input limit is 25V)
330  voltage = 24.0;
331  }
332  volt = busvoodoo_vreg_get(BUSVOODOO_3V3_CHANNEL); // get reference voltage
333  if (isnan(voltage)) {
334  return NAN;
335  }
336  uint16_t dac_set = BUSVOODOO_HV_SET(voltage)/volt*4095; // DAC value corresponding to the voltage
337  dac_load_data_buffer_single(dac_set, RIGHT12, BUSVOODOO_HVCTL_CHANNEL); // set output so the voltage regulator is set to desired output voltage
338  dac_software_trigger(BUSVOODOO_HVCTL_CHANNEL); // transfer the value to the DAC
339  dac_enable(BUSVOODOO_HVCTL_CHANNEL); // enable DAC
340  gpio_clear(GPIO(BUSVOODOO_HVEN_PORT), GPIO(BUSVOODOO_HVEN_PIN)); // enable HV voltage regulator
341  }
342  sleep_ms(100); // let the voltage regulator start and voltage settle
343  volt = busvoodoo_vreg_get(BUSVOODOO_HV_CHANNEL); // get HV voltage
344 
345  return volt; // return measured voltage
346 }
347 
349 {
350  if (on) { // enable embedded pull-ups
351  gpio_clear(GPIO(BUSVOODOO_OEPULLUP_PORT), GPIO(BUSVOODOO_OEPULLUP_PIN)); // switch on embedded pull-ups
352  } else { // disable embedded pull-ups
353  gpio_set(GPIO(BUSVOODOO_OEPULLUP_PORT), GPIO(BUSVOODOO_OEPULLUP_PIN)); // switch off embedded pull-up
354  }
355  return busvoodoo_vreg_get(BUSVOODOO_LV_CHANNEL); // set voltage on adjustable voltage regulator to be used by the embedded pull-ups
356 }
357 
359 static void busvoodoo_led_update(void)
360 {
361  if (busvoodoo_global_led_blue && busvoodoo_global_led_red) { // both LEDs should be on
362  led_blink(0.01, 0.5); // enable both LEDs (alternating at 100Hz)
363  } else if (busvoodoo_global_led_blue) { // only blue LED should be on
364  led_blue(); // enable only blue LED
365  } else if (busvoodoo_global_led_red) { // only red LED should be on
366  led_red(); // enable only red LED
367  } else { // no LED should be on
368  led_off(); // disable both LEDs
369  }
370 }
371 
372 void busvoodoo_led_blue_pulse(uint16_t ms)
373 {
374  timer_disable_counter(TIM(BUSVOODOO_LED_TIMER)); // disable counter while changing LEDs to avoid coherence errors (at the cost of time precision)
375  if (ms>UINT16_MAX/2) { // enforce maximum
376  ms = UINT16_MAX/2;
377  }
378 
379  if (0==ms) { // disable LED
380  busvoodoo_global_led_blue = false; // remember we disabled the blue LED
381  } else {
382  busvoodoo_global_led_blue = true; // remember the blue LED should be on
383  timer_set_oc_value(TIM(BUSVOODOO_LED_TIMER), TIM_OC1, timer_get_counter(TIM(BUSVOODOO_LED_TIMER))+ms*2); // use capture 1 to set LED timer
384  timer_clear_flag(TIM(BUSVOODOO_LED_TIMER), TIM_SR_CC1IF); // clear flag before enabling
385  timer_enable_irq(TIM(BUSVOODOO_LED_TIMER), TIM_DIER_CC1IE); // enable capture 1 for blue LED
386  }
387  busvoodoo_led_update(); // update LED status
388  timer_enable_counter(TIM(BUSVOODOO_LED_TIMER)); // re-enable timer
389 }
390 
391 void busvoodoo_led_red_pulse(uint16_t ms)
392 {
393  timer_disable_counter(TIM(BUSVOODOO_LED_TIMER)); // disable counter while changing LEDs to avoid coherence errors (at the cost of time precision)
394  if (ms>UINT16_MAX/2) { // enforce maximum
395  ms = UINT16_MAX/2;
396  }
397 
398  if (0==ms) { // disable LED
399  busvoodoo_global_led_red = false; // remember we disabled the blue LED
400  } else {
401  busvoodoo_global_led_red = true; // remember the blue LED should be on
402  timer_set_oc_value(TIM(BUSVOODOO_LED_TIMER), TIM_OC2, timer_get_counter(TIM(BUSVOODOO_LED_TIMER))+ms*2); // use capture 1 to set LED timer
403  timer_clear_flag(TIM(BUSVOODOO_LED_TIMER), TIM_SR_CC2IF); // clear flag before enabling
404  timer_enable_irq(TIM(BUSVOODOO_LED_TIMER), TIM_DIER_CC2IE); // enable capture 2 for red LED
405  }
406  busvoodoo_led_update(); // update LED status
407  timer_enable_counter(TIM(BUSVOODOO_LED_TIMER)); // re-enable timer
408 }
409 
410 bool busvoodoo_global_actions(char* actions, bool perform, bool (*action_handler)(const char* action, uint32_t repetition, bool perform))
411 {
412  char* action_start = actions; // start of the current action
413  bool last_action = false; // is the current action the last one
414  while ('\0'!=*action_start && !last_action) {
415  // find end of action
416  char* action_end = action_start+1;
417  if ('"'==*action_start || '\''==*action_start) { // start of string
418  while ('\0'!=*action_end && *action_end!=*action_start) {
419  action_end++;
420  }
421  if (*action_end!=*action_start) { // action not ended correctly
422  return false;
423  }
424  action_end++; // go the end of action
425  } else { // just look for a separation
426  while ('\0'!=*action_end && ':'!=*action_end && ' '!=*action_end && ','!=*action_end) {
427  action_end++;
428  }
429  }
430  // find start of next action
431  char *separation = action_end; // position of separation to next action
432  while ('\0'!=*separation && ' '!=*separation && ','!=*separation) { // find separation or end
433  separation++;
434  }
435  if ('\0'==*separation) {
436  last_action = true; // remember we reached the end of the string
437  } else {
438  *separation = '\0'; // end the action to form a string
439  }
440  // get multiplier
441  uint32_t multiplier = 1; // the number of times the action should be performed
442  if (separation>action_end) { // there is something after the action
443  if (':'==*action_end) { // multiplier sign found
444  if (separation==action_end+1) { // no digit present
445  return false; // malformed action
446  }
447  for (char* digit=action_end+1; digit<separation; digit++) { // check if all the characters are digits
448  if (*digit<'0' || *digit>'9') { // not a digit
449  return false; // malformed string
450  }
451  }
452  multiplier = strtol(action_end+1, NULL, 10); // parse multiplier number
453  } else { // unknown sign after action
454  return false; // malformed action
455  }
456  }
457  // perform action
458  *action_end = '\0'; // end action string
459  if (!(*action_handler)(action_start, multiplier, perform)) { // perform action
460  return false; // action if malformed
461  }
462  // go to next action
463  if (!last_action) {
464  action_start = separation+1;
465  }
466  }
467  return true; // all went well
468 }
469 
470 /* command handlers */
471 
476 {
477  float voltage;
478  if (NULL==argument || 0==strlen(argument)) {
479  if (gpio_get(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN))) { // check if power rails are switch on (enable low)
480  goto power_off;
481  } else {
482  goto power_on;
483  }
484  } else if (0==strcmp(argument, "on")) {
485  if (busvoodoo_vout_switch(true)) { // switch power rail on
486  printf("power rails switched on\n");
487  } else {
488  printf("power rails switched on but malfunctioning\n");
489  }
490 power_on:
491  voltage = busvoodoo_vreg_get(BUSVOODOO_5V_CHANNEL); // get 5V power rail voltage
492  printf("5V power rail: %.2fV\n", voltage);
493  voltage = busvoodoo_vreg_get(BUSVOODOO_3V3_CHANNEL); // get 3.3V power rail voltage
494  printf("3V3 power rail: %.2fV\n", voltage);
495  } else if (0==strcmp(argument, "off")) {
496  busvoodoo_vout_switch(false); // switch power rail off
497  printf("power rails switched off\n");
498 power_off:
499  printf("5V power rail: off\n");
500  printf("3V3 power rail: off\n");
501  } else {
502  printf("option malformed: %s\n", argument);
503  }
504 }
505 
509 static void busvoodoo_global_lv(void* argument)
510 {
511  if (NULL==argument) {
512  if (!gpio_get(GPIO(BUSVOODOO_5VPULLUP_PORT), GPIO(BUSVOODOO_5VPULLUP_PIN))) { // 5V input enabled
513  printf("5V power rail used");
514  } else if (gpio_get(GPIO(BUSVOODOO_LVEN_PORT), GPIO(BUSVOODOO_LVEN_PIN))) { // LV voltage regulator used
515  printf("adjustable voltage regulator used");
516  } else {
517  printf("external voltage input");
518  }
519  float voltage = busvoodoo_vreg_get(BUSVOODOO_LV_CHANNEL); // get LV voltage
520  // print LV voltage
521  if (voltage < 0.1) {
522  printf(": 0.00V\n");
523  } else {
524  printf(": %.2fV\n", voltage);
525  }
526  } else {
527  double voltage = *((double*)argument); // get desired voltage
528  if (0==voltage) {
529  printf("LV rail switched off");
530  } else {
531  printf("LV rail set to %.2fV", voltage);
532  }
533  voltage = busvoodoo_lv_set(voltage); // set LV voltage
534  // print LV voltage
535  if (voltage < 0.1) {
536  printf(": 0.00V\n");
537  } else {
538  printf(": %.2fV\n", voltage);
539  }
540  }
541 }
542 
546 static void busvoodoo_global_hv(void* argument)
547 {
548  if (!busvoodoo_full) {
549  printf("function not available on BusVoodoo light");
550  return;
551  }
552  if (NULL==argument) {
553  printf("high voltage regulator switched %s: ", gpio_get(GPIO(BUSVOODOO_HVEN_PORT), GPIO(BUSVOODOO_HVEN_PIN)) ? "off" : "on");
554  float voltage = busvoodoo_vreg_get(BUSVOODOO_HV_CHANNEL); // get HV voltage
555  // print LV voltage
556  if (voltage < 0.1) {
557  printf("0.00V\n");
558  } else {
559  printf("%.2fV\n", voltage);
560  }
561  } else {
562  double voltage = *((double*)argument); // get desired voltage
563  printf("high voltage rail ");
564  if (voltage<=3.3) {
565  printf("switched off");
566  } else {
567  printf("set to %.2fV", voltage);
568  }
569  voltage = busvoodoo_hv_set(voltage); // set HV voltage
570  // print HV voltage
571  if (voltage < 0.1) {
572  printf(": 0.00V\n");
573  } else {
574  printf(": %.2fV\n", voltage);
575  }
576  }
577 }
578 
583 {
584  (void)argument; // argument is not used
585  bool no_pinout = true; // it no pinout has been displays
586 
587  // display RS/CAN connector pinout
588  if (busvoodoo_full) { // only display on full version of the board
589  bool pin_used = false; // if no pins are used
590  for (uint8_t i=0; i<LENGTH(busvoodoo_global_pinout_rscan); i++) { // verify if one of the pins is used
591  pin_used |= (NULL!=busvoodoo_global_pinout_rscan[i]); // verify if pin is used
592  }
593  if (pin_used) {
594  // count the space used to display the pins
595  uint8_t space = 0; // no integer overflow protected (it's only cosmetic)
596  for (uint8_t i=0; i<LENGTH(busvoodoo_global_pinout_rscan); i++) {
597  if (NULL==busvoodoo_global_pinout_rscan[i]) {
598  space += 1; // only x will be shown
599  } else {
600  space += strlen(busvoodoo_global_pinout_rscan[i]); // add size of pin name
601  }
602  }
603  space += LENGTH(busvoodoo_global_pinout_rscan)-1; // add the spaces between the names
604  // display pinout
605  printf("RS/CAN connector pinout:\n");
606  // display top line
607  printf("+");
608  for (uint8_t i=0; i<space; i++) {
609  printf("-");
610  }
611  printf("+\n");
612  // display pin names
613  printf("|");
614  for (int8_t i=LENGTH(busvoodoo_global_pinout_rscan)-1; i>=0; i--) {
615  if (NULL==busvoodoo_global_pinout_rscan[i]) {
616  printf("x"); // x stands for pin not used
617  } else {
618  printf("%s", busvoodoo_global_pinout_rscan[i]); // print pin name
619  }
620  if (i>0) {
621  printf(" "); // print space between the pin names
622  }
623  }
624  printf("|\n");
625  // display bottom line
626  printf("+");
627  for (uint8_t i=0; i<space; i++) {
628  printf("-");
629  }
630  printf("+\n");
631  no_pinout = false; // remember a pinout has been shown
632  }
633  }
634 
635  // display I/O connector pinout
636  bool pin_used = false; // if no pins are used
637  for (uint8_t i=0; i<LENGTH(busvoodoo_global_pinout_io); i++) { // verify if one of the pins is used
638  pin_used |= (NULL!=busvoodoo_global_pinout_io[i]); // verify if pin is used
639  }
640  if (pin_used) {
641  // count the space used to display the pins (no integer overflow protected, it's only cosmetic)
642  uint8_t spaces[5] = {0}; // maximum spaces used by top and bottom pins
643  for (uint8_t i=0; i<LENGTH(spaces); i++) {
644  if (NULL==busvoodoo_global_pinout_io[i*2]) {
645  spaces[i] = 1; // only x will be shown
646  } else {
647  spaces[i] = strlen(busvoodoo_global_pinout_io[i*2]); // remember size of pin name
648  }
649  if (NULL==busvoodoo_global_pinout_io[i*2+1]) {
650  if (spaces[i]<1) {
651  spaces[i] = 1; // only x will be shown
652  }
653  } else {
654  if (spaces[i]<strlen(busvoodoo_global_pinout_io[i*2+1])) {
655  spaces[i] = strlen(busvoodoo_global_pinout_io[i*2+1]); // remember bigger size of pin name
656  }
657  }
658  }
659  // display pinout
660  printf("I/O connector pinout:\n");
661  // display top line
662  printf("+");
663  for (uint16_t i=0; i<(uint16_t)(spaces[4]+spaces[3]+1); i++) {
664  printf("-");
665  }
666  for (uint16_t i=0; i<(uint16_t)(spaces[2]+2); i++) {
667  printf(" ");
668  }
669  for (uint16_t i=0; i<(uint16_t)(spaces[1]+spaces[0]+1); i++) {
670  printf("-");
671  }
672  printf("+\n");
673  // display top pin names
674  printf("|");
675  for (int8_t i=4; i>=0; i--) {
676  if (NULL==busvoodoo_global_pinout_io[i*2]) {
677  printf("x"); // x stands for pin not used
678  for (int16_t j=0; j<spaces[i]-1; j++) {
679  printf(" "); // pad to match to bottom pin
680  }
681  } else {
682  printf("%s", busvoodoo_global_pinout_io[i*2]); // print pin name
683  for (int16_t j=0; j+strlen(busvoodoo_global_pinout_io[i*2])<spaces[i]; j++) {
684  printf(" "); // pad to match to bottom pin
685  }
686  }
687  if (i>0) {
688  printf(" "); // print space between the pin names
689  }
690  }
691  printf("|\n");
692  // display bottom pin names
693  printf("|");
694  for (int8_t i=4; i>=0; i--) {
695  if (NULL==busvoodoo_global_pinout_io[i*2+1]) {
696  printf("x"); // x stands for pin not used
697  for (int16_t j=0; j<spaces[i]-1; j++) {
698  printf(" "); // pad to match to bottom pin
699  }
700  } else {
701  printf("%s", busvoodoo_global_pinout_io[i*2+1]); // print pin name
702  for (int16_t j=0; j+strlen(busvoodoo_global_pinout_io[i*2+1])<spaces[i]; j++) {
703  printf(" "); // pad to match to bottom pin
704  }
705  }
706  if (i>0) {
707  printf(" "); // print space between the pin names
708  }
709  }
710  printf("|\n");
711  // display bottom line
712  printf("+");
713  for (uint16_t i=0; i<spaces[4]+1+spaces[3]+1+spaces[2]+1+spaces[1]+1+spaces[0]; i++) {
714  printf("-");
715  }
716  printf("+\n");
717  no_pinout = false; // remember a pinout has been shown
718  }
719 
720  // in case nothing has been displayed
721  if (no_pinout) {
722  printf("no pins are used\n");
723  }
724 }
725 
728  {
729  'P',
730  "power",
731  "switch 3V3 and 5V power rails on/off",
733  "[on|off]",
735  },
736  {
737  'L',
738  "LV",
739  "set voltage on low voltage power rail (0, 0.3-4.8, 5V)",
741  "[voltage]",
743  },
744  {
745  'H',
746  "HV",
747  "set voltage on high voltage power rail (0, 3.3-24V)",
749  "[voltage]",
751  },
752  {
753  'p',
754  "pinout",
755  "show connector pinout",
757  NULL,
759  },
760 };
761 
763 
766 {
767  if (timer_get_flag(TIM(BUSVOODOO_LED_TIMER), TIM_SR_CC1IF)) { // blue LED timeout
768  timer_clear_flag(TIM(BUSVOODOO_LED_TIMER), TIM_SR_CC1IF); // clear flag
769  timer_disable_irq(TIM(BUSVOODOO_LED_TIMER), TIM_DIER_CC1IE); // disable capture 1 for blue LED
770  busvoodoo_global_led_blue = false; // remember blue LED should be disabled
771  busvoodoo_led_update(); // update LED status
772  } else if (timer_get_flag(TIM(BUSVOODOO_LED_TIMER), TIM_SR_CC2IF)) { // red LED timeout
773  timer_clear_flag(TIM(BUSVOODOO_LED_TIMER), TIM_SR_CC2IF); // clear flag
774  timer_disable_irq(TIM(BUSVOODOO_LED_TIMER), TIM_DIER_CC2IE); // disable capture 2 for red LED
775  busvoodoo_global_led_red = false; // remember red LED should be disabled
776  busvoodoo_led_update(); // update LED status
777  }
778 }
#define BUSVOODOO_5V_CHANNEL
ADC channel to measure 3.3V rail.
float busvoodoo_hv_set(float voltage)
set voltage on high voltage adjustable voltage regulator
#define BUSVOODOO_HVCTL_CHANNEL
DAC channel to control HV output voltage.
#define TIM_ISR(x)
get interrupt service routine for timer base on TIM identifier
Definition: global.h:113
command menu entry
Definition: menu.h:31
const struct menu_command_t busvoodoo_global_commands[]
list of supported commands
static void busvoodoo_global_power(void *argument)
switch 3V3 and 5V power rails on/off
BusVoodoo global definitions and methods (API)
#define BUSVOODOO_HVEN_PIN
high voltage (HV) enable pin (active low)
#define BUSVOODOO_HW_VERSION_CHANNEL
ADC to identify hardware version.
static void busvoodoo_global_lv(void *argument)
set lV linear drop-out voltage regulator voltage
void busvoodoo_led_red_pulse(uint16_t ms)
pulse red LED for short duration
#define BUSVOODOO_LVCTL_PORT
pin to control LV output voltage
bool busvoodoo_vout_switch(bool on)
switch 3V3 and 5V power outputs on I/O connector
#define BUSVOODOO_RS232_EN_PORT
RS-232 pin to enable receiver (active low, pulled up)
#define BUSVOODOO_HW_VERSION_PORT
pin to identify hardware version
void led_off(void)
switch off board LED
Definition: global.c:82
static void busvoodoo_global_hv(void *argument)
set HV step-up voltage regulator voltage
#define NVIC_TIM_IRQ(x)
get NVIC IRQ for timer base on TIM identifier
Definition: global.h:111
#define BUSVOODOO_HV_SET(x)
voltage to output for the DAC to set the desired HV output voltage (based on resistor values on the H...
#define BUSVOODOO_HVCTL_PORT
pin to control HV output voltage
#define BUSVOODOO_HVEN_PORT
high voltage (HV) enable pin (active low)
#define BUSVOODOO_RS232_CTS_PORT
RS-232 Clear-To-Send input pin.
float busvoodoo_lv_set(float voltage)
set voltage on low voltage adjustable voltage regulator
#define BUSVOODOO_LVEN_PIN
low voltage (LV) enable pin (active high)
const char * busvoodoo_global_pinout_rscan[5]
RS/CAN connector pinout.
#define BUSVOODOO_LV_SET(x)
voltage to output for the DAC to set the desired LV output voltage (based on resistor values on the L...
const uint32_t busvoodoo_io_pins[13]
pin of individual signals
#define BUSVOODOO_RS232_TX_PORT
RS-232 Transmit output pin.
global definitions and methods (API)
enum menu_argument_t argument
what kind of argument it accepts
Definition: menu.h:35
#define GPIO(x)
get GPIO based on GPIO identifier
Definition: global.h:103
#define BUSVOODOO_RS485_RX_PORT
RS-485 Receive input pin.
void busvoodoo_led_blue_pulse(uint16_t ms)
pulse blue LED for short duration
void sleep_us(uint32_t duration)
go to sleep for some microseconds
Definition: global.c:144
#define BUSVOODOO_CAN_EN_PORT
signal to power CAN transceiver (active low, pulled high)
#define BUSVOODOO_RS485_RE_PORT
RS-485 pin to enable receiver (active low, pulled up)
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_TIM(x)
get RCC for timer based on TIM identifier
Definition: global.h:109
const uint32_t busvoodoo_io_ports[13]
port of individual signals
static volatile bool busvoodoo_global_led_blue
blue LED status
#define BUSVOODOO_RS485_TX_PORT
RS-485 Transmit output pin.
#define BUSVOODOO_OEPULLUP_PIN
bus switch output enable pin to enable embedded pull-ups (active low)
#define ADC12_IN_PORT(x)
get port based on ADC12_IN identifier
Definition: global.h:211
#define BUSVOODOO_RS232_CTS_PIN
RS-232 Clear-To-Send input pin.
#define BUSVOODOO_LV_CHANNEL
ADC channel to measure LV rail.
#define BUSVOODOO_RS232_TX_PIN
RS-232 Transmit output pin.
#define BUSVOODOO_RS485_DE_PORT
RS-485 pin to enable transmitter (active high, pulled low)
#define BUSVOODOO_RS232_RTS_PIN
RS-232 Request-To-Send output pin.
const uint8_t busvoodoo_io_groups[13]
which I/O pin (group) does the signal belong to
#define BUSVOODOO_CAN_RX_PIN
CAN Receive input pin.
#define ADC12_IN_PIN(x)
get pin based on ADC12_IN identifier
Definition: global.h:229
#define BUSVOODOO_HV_CHANNEL
ADC channel to measure HV rail.
const char * busvoodoo_global_pinout_io[10]
I/O connector pinout.
#define BUSVOODOO_LVCTL_PIN
pin to control LV output voltage
#define BUSVOODOO_RS232_EN_PIN
RS-232 pin to enable receiver (active low, pulled up)
float busvoodoo_vreg_get(uint8_t channel)
read voltage from power rail
const char * busvoodoo_io_names[13]
I/O individual signal names.
char busvoodoo_global_string[64]
shared string buffer, i.e.
#define BUSVOODOO_5VPULLUP_PIN
5V pull-up enable pin (active low)
const uint8_t busvoodoo_global_commands_nb
number supported commands
#define BUSVOODOO_VOUTEN_PORT
voltage output (5V and 3.3V) enable pin (active low)
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
Definition: global.c:159
#define BUSVOODOO_CAN_TX_PIN
CAN Transmit output pin.
#define BUSVOODOO_VOUTEN_PIN
voltage output (5V and 3.3V) enable pin (active low)
#define BUSVOODOO_LVCTL_CHANNEL
DAC channel to control LV output voltage.
#define BUSVOODOO_HW_VERSION_PIN
pin to identify hardware version
#define BUSVOODOO_RS232_RX_PORT
RS-232 Receive input pin.
#define BUSVOODOO_RS485_DE_PIN
RS-485 pin to enable transmitter (active high, pulled low)
#define BUSVOODOO_LED_TIMER
timer peripheral
#define BUSVOODOO_LVEN_PORT
low voltage (LV) enable pin (active high)
float busvoodoo_embedded_pullup(bool on)
enable embedded pull-up resistors
static void busvoodoo_led_update(void)
update LED status according to LED flags
#define BUSVOODOO_RS232_RTS_PORT
RS-232 Request-To-Send output pin.
static void busvoodoo_global_pinout(void *argument)
display I/O and RS/CAN connector pinouts
#define LENGTH(x)
get the length of an array
Definition: global.h:26
#define BUSVOODOO_RS485_RE_PIN
RS-485 pin to enable receiver (active low, pulled up)
#define ADC_CHANNEL(x)
get channel based on ADC12_IN identifier
Definition: global.h:265
#define BUSVOODOO_CAN_RX_PORT
CAN Receive input pin.
#define BUSVOODOO_OEPULLUP_PORT
bus switch output enable pin to enable embedded pull-ups (active low)
static volatile bool busvoodoo_global_led_red
red LED status
#define BUSVOODOO_5VPULLUP_PORT
5V pull-up enable pin (active low)
#define BUSVOODOO_RS232_RX_PIN
RS-232 Receive input pin.
#define TIM(x)
get TIM based on TIM identifier
Definition: global.h:107
#define BUSVOODOO_RS485_RX_PIN
RS-485 Receive input pin.
static const float busvoodoo_version_voltages[]
hardware version voltages, calculated from divider ratios, starting with version A ...
#define BUSVOODOO_RS485_TX_PIN
RS-485 Transmit output pin.
void busvoodoo_safe_state(void)
set safe state by disabling all outputs
char busvoodoo_version
version of the hardware board
void busvoodoo_setup(void)
setup BusVoodoo board
#define BUSVOODOO_RS232_SHDN_PORT
RS-232 pin to enable transmitter (active high, pulled low)
#define BUSVOODOO_3V3_CHANNEL
ADC channel to measure 5V rail.
#define BUSVOODOO_RS232_SHDN_PIN
RS-232 pin to enable transmitter (active high, pulled low)
#define BUSVOODOO_HVCTL_PIN
pin to control HV output voltage
#define RCC_ADC12_IN(x)
get RCC based on ADC12_IN identifier
Definition: global.h:247
#define BUSVOODOO_CAN_TX_PORT
CAN Transmit output pin.
#define BUSVOODOO_CAN_EN_PIN
signal to power CAN transceiver (active low, pulled high)