diff --git a/application.c b/application.c index ed4aa81..dbd9e1a 100644 --- a/application.c +++ b/application.c @@ -44,97 +44,11 @@ #include "uart.h" // USART utilities #include "usb_cdcacm.h" // USB CDC ACM utilities #include "terminal.h" // handle the terminal interface - -//#include "rs485.h" // RS-485 utilities -//#include "rs232.h" // RS-232 utilities -//#include "i2c_master.h" // I2C utilities +#include "busvoodoo_global.h" // BusVoodoo definitions +#include "busvoodoo_hiz.h" // BusVoodoo HiZ mode utilities #define WATCHDOG_PERIOD 10000 /**< watchdog period in ms */ -/** @defgroup busvoodoo_peripherals peripheral pin definitions - * @{ - */ -#define BUSVOODOO_5VPULLUP_PORT B /**< 5V pull-up enable pin (active low) */ -#define BUSVOODOO_5VPULLUP_PIN 4 /**< 5V pull-up enable pin (active low) */ -#define BUSVOODOO_OEPULLUP_PORT A /**< bus switch output enable pin to enable embedded pull-ups (active low) */ -#define BUSVOODOO_OEPULLUP_PIN 15 /**< bus switch output enable pin to enable embedded pull-ups (active low) */ -#define BUSVOODOO_XVEN_PORT A /**< xV enable pin (active high) */ -#define BUSVOODOO_XVEN_PIN 6 /**< xV enable pin (active high) */ -#define BUSVOODOO_12VEN_PORT A /**< 12V enable pin (active low) */ -#define BUSVOODOO_12VEN_PIN 7 /**< 12V enable pin (active low) */ -#define BUSVOODOO_VOUTEN_PORT B /**< voltage output (5V and 3.3V) enable pin (active low) */ -#define BUSVOODOO_VOUTEN_PIN 3 /**< voltage output (5V and 3.3V) enable pin (active low) */ -/** @} */ - -/** @defgroup busvoodoo_adc ADC inputs to measure voltages from voltage regulators - * @{ - */ -#define BUSVOODOO_3V3_CHANNEL 12 /**< ADC channel to measure 5V rail */ -#define BUSVOODOO_5V_CHANNEL 9 /**< ADC channel to measure 3.3V rail */ -#define BUSVOODOO_XV_CHANNEL 11 /**< ADC channel to measure xV rail */ -#define BUSVOODOO_12V_CHANNEL 15 /**< ADC channel to measure 12V rail */ -/** @} */ - -/** @defgroup busvoodoo_dac DAC output to set voltages of voltage regulators - * @{ - */ -#define BUSVOODOO_XVCTL_PORT A /**< pin to control xV output voltage */ -#define BUSVOODOO_XVCTL_PIN 4 /**< pin to control xV output voltage */ -#define BUSVOODOO_XVCTL_CHANNEL CHANNEL_1 /**< DAC channel to control xV output voltage */ -#define BUSVOODOO_XV_DEFAULT (0.8*(1+30.0/10.0)) /**< default (when not driven) xV voltage regulator output voltage based on R1 and R2 */ -#define BUSVOODOO_XV_TEST 2.5 /**< target xV output voltage to test if we can set control the xV voltage regulator */ -#define BUSVOODOO_XV_SET(x) ((0.8*(1+30.0/10.0)-x)*(10.0/30.0)+0.8) /**< voltage to output for the DAC to set the desired xV output voltage (based on resistor values on the xV adjust pins and xV voltage reference) */ -#define BUSVOODOO_12VCTL_PORT A /**< pin to control 12V output voltage */ -#define BUSVOODOO_12VCTL_PIN 5 /**< pin to control 12V output voltage */ -#define BUSVOODOO_12VCTL_CHANNEL CHANNEL_2 /**< DAC channel to control 12V output voltage */ -#define BUSVOODOO_12V_DEFAULT (1.25*(1+100.0/10.0)) /**< default (when not driven) 12V voltage regulator output voltage based on R1 and R2 */ -#define BUSVOODOO_12V_TEST 12.0 /**< target 12V output voltage to test if we can set control the 12V voltage regulator */ -#define BUSVOODOO_12V_SET(x) ((1.25*(1+100.0/10.0)-x)*(10.0/100.0)+1.25) /**< voltage to output for the DAC to set the desired -12V output voltage (based on resistor values on the 12V adjust pins and 12V voltage reference) */ -/** @} */ - -/** @defgroup busvoodoo_rs232 RS-232 transceiver connection definition - * @{ - */ -#define BUSVOODOO_RS232_EN_PORT B /**< RS-232 pin to enable receiver (active low, pulled up) */ -#define BUSVOODOO_RS232_EN_PIN 5 /**< RS-232 pin to enable receiver (active low, pulled up) */ -#define BUSVOODOO_RS232_SHDN_PORT C /**< RS-232 pin to enable transmitter (active high, pulled low) */ -#define BUSVOODOO_RS232_SHDN_PIN 15 /**< RS-232 pin to enable transmitter (active high, pulled low) */ -#define BUSVOODOO_RS232_RTS_PORT A /**< RS-232 Request-To-Send output pin */ -#define BUSVOODOO_RS232_RTS_PIN 1 /**< RS-232 Request-To-Send output pin */ -#define BUSVOODOO_RS232_CTS_PORT A /**< RS-232 Clear-To-Send input pin */ -#define BUSVOODOO_RS232_CTS_PIN 0 /**< RS-232 Clear-To-Send input pin */ -#define BUSVOODOO_RS232_TX_PORT A /**< RS-232 Transmit output pin */ -#define BUSVOODOO_RS232_TX_PIN 2 /**< RS-232 Transmit output pin */ -#define BUSVOODOO_RS232_RX_PORT A /**< RS-232 Receive input pin */ -#define BUSVOODOO_RS232_RX_PIN 3 /**< RS-232 Receive input pin */ -/** @} */ - -/** @defgroup busvoodoo_can CAN transceiver connection definition - * @{ - */ -#define BUSVOODOO_CAN_EN_PORT C /**< CAN pin to enable transceiver (active high, pulled low) */ -#define BUSVOODOO_CAN_EN_PIN 14 /**< CAN pin to enable transceiver (active high, pulled low) */ -#define BUSVOODOO_CAN_S_PORT C /**< CAN pin to set to silent mode (active low, pulled high) */ -#define BUSVOODOO_CAN_S_PIN 13 /**< CAN pin to set to silent mode (active low, pulled high) */ -#define BUSVOODOO_CAN_TX_PORT B /**< CAN Transmit output pin */ -#define BUSVOODOO_CAN_TX_PIN 9 /**< CAN Transmit output pin */ -#define BUSVOODOO_CAN_RX_PORT B /**< CAN Receive input pin */ -#define BUSVOODOO_CAN_RX_PIN 8 /**< CAN Receive input pin */ -/** @} */ - -/** @defgroup busvoodoo_io I/O connector pin definition - * @{ - */ -static const char* busvoodoo_io_names[13] = {"I2C_SMBA/SPI_NSS/I2S_WS", "SDIO_CMD", "USART_CTS/SPI_SCK/I2S_CK", "SDIO_D3/UART_RX", "I2C_SDA/USART_RX", "SDIO_D0", "SPI_MOSI/I2S_SD", "SDIO_CK/USART_CK", "I2C_SCL/USART_TX", "SDIO_D1", "I2S_MCK", "USART_RTS/SPI_MISO", "SDIO_D2/UART_TX"}; /**< I/O individual signal names */ -static const uint32_t busvoodoo_io_ports[13] = {GPIOB, GPIOD, GPIOB, GPIOC, GPIOB, GPIOC, GPIOB, GPIOC, GPIOB, GPIOC, GPIOC, GPIOB, GPIOC}; /**< port of individual signals */ -static const uint32_t busvoodoo_io_pins[13] = {GPIO12, GPIO2, GPIO13, GPIO11, GPIO11, GPIO8, GPIO15, GPIO12, GPIO10, GPIO9, GPIO6, GPIO14, GPIO10}; /**< pin of individual signals */ -static const uint8_t busvoodoo_io_groups[13] = {6, 6, 4, 4, 1, 1, 5, 5, 2, 2, 3, 3, 3}; /**< which I/O pin (group) does the signal belong to */ -/** @} */ - -/** is the BusVoodoo board fully populated (with 12V voltage regulator, RS-232, RS-485, CAN transceiver on the back side) */ -static bool busvoodoo_full = false; - size_t putc(char c) { size_t length = 0; // number of characters printed @@ -175,692 +89,6 @@ static bool wait_space(void) } } -/** set safe state by disabling all outputs */ -static void safe_state(void) -{ - // disable voltage outputs - gpio_set(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // disable 5V and 3.3V output on connector - 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) - gpio_clear(GPIO(BUSVOODOO_XVEN_PORT), GPIO(BUSVOODOO_XVEN_PIN)); // disable xV voltage regulator - gpio_set_mode(GPIO(BUSVOODOO_XVEN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUSVOODOO_XVEN_PIN)); // set pin as output (push-pull, pulled low for safety) - gpio_set(GPIO(BUSVOODOO_12VEN_PORT), GPIO(BUSVOODOO_12VEN_PIN)); // disable 12V voltage regulator - gpio_set_mode(GPIO(BUSVOODOO_12VEN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(BUSVOODOO_12VEN_PIN)); // set pin as output (open-drain pulled high to disable the pMOS) - - // set DAC channel back to analog - gpio_set_mode(GPIO(BUSVOODOO_XVCTL_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO(BUSVOODOO_XVCTL_PIN)); // set xV pin as analog - gpio_set_mode(GPIO(BUSVOODOO_12VCTL_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO(BUSVOODOO_12VCTL_PIN)); // set 12V pin as analog - - // disable embedded pull-ups - 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) - gpio_set(GPIO(BUSVOODOO_5VPULLUP_PORT), GPIO(BUSVOODOO_5VPULLUP_PIN)); // set pin high to disable 5V embedded pull-up - 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) - gpio_set(GPIO(BUSVOODOO_OEPULLUP_PORT), GPIO(BUSVOODOO_OEPULLUP_PIN)); // set pin high to disable embedded pull-up bus switch - 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) - - // disable all signal I/O outputs - for (uint8_t pin=0; pin5.5) { - printf("5V power rail voltage is too high: %.2fV\n", voltage); -#if DEBUG - while (true); -#else - goto error; -#endif - } - - // check 3.3V power rail - voltage = rail_voltage(BUSVOODOO_3V3_CHANNEL); // get 3.3V power rail voltage - if (voltage<3.0) { - printf("3.3V power rail voltage is too low: %.2fV\n", voltage); -#if DEBUG - while (true); -#else - goto error; -#endif - } else if (voltage>3.6) { - printf("3.3V power rail voltage is too high: %.2fV\n", voltage); -#if DEBUG - while (true); -#else - goto error; -#endif - } - - // test 5V and 3.3V outputs - gpio_clear(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // enable Vout - sleep_ms(1); // wait a bit for voltage to settle - voltage = rail_voltage(BUSVOODOO_5V_CHANNEL); // get 5V power rail voltage - if (voltage<4.0) { - printf("5V power rail voltage is too low when 5V output is enabled: %.2fV\n", voltage); -#if DEBUG - while (true); -#else - goto error; -#endif - } else if (voltage>5.5) { - printf("5V power rail voltage is too high when 5V output is enabled: %.2fV\n", voltage); -#if DEBUG - while (true); -#else - goto error; -#endif - } - voltage = rail_voltage(BUSVOODOO_3V3_CHANNEL); // get 3.3V power rail voltage - if (voltage<3.0) { - printf("3.3V power rail voltage is too low when 3V3 output is enabled: %.2fV\n", voltage); -#if DEBUG - while (true); -#else - goto error; -#endif - } else if (voltage>3.6) { - printf("3.3V power rail voltage is too high when 3V3 is enabled: %.2fV\n", voltage); -#if DEBUG - while (true); -#else - goto error; -#endif - } - gpio_set(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // disable Vout - - // check xV voltage regulator - gpio_clear(GPIO(BUSVOODOO_XVEN_PORT), GPIO(BUSVOODOO_XVEN_PIN)); // disable xV voltage regulator - sleep_ms(1); // let voltage settle - voltage = rail_voltage(BUSVOODOO_XV_CHANNEL); // get xV voltage - if (voltage>0.2) { // ensure the output is at 0V when the regulator is not enabled - printf("xV voltage is %.2fV instead of 0V when the regulator is disabled\n", voltage); -#if DEBUG - while (true); -#else - goto error; -#endif - } - gpio_set(GPIO(BUSVOODOO_XVEN_PORT), GPIO(BUSVOODOO_XVEN_PIN)); // enable xV voltage regulator - sleep_ms(5); // let the voltage regulator start and voltage settle - voltage = rail_voltage(BUSVOODOO_XV_CHANNEL); // get xV voltage - // without being driven it should be around the default voltage - if (voltageBUSVOODOO_XV_DEFAULT+0.2) { - printf("xV voltage is higher (%.2fV) than expected (%.2fV) when the regulator is enabled\n", voltage, BUSVOODOO_XV_DEFAULT); -#if DEBUG - while (true); -#else - goto error; -#endif - } - - // check if we can control xV - voltage = rail_voltage(BUSVOODOO_3V3_CHANNEL); // get reference voltage - if (isnan(voltage)) { - printf("can get 3V3 rail voltage"); - goto error; - } - uint16_t dac_set = BUSVOODOO_XV_SET(BUSVOODOO_XV_TEST)/voltage*4095; // DAC value corresponding to the voltage - dac_load_data_buffer_single(dac_set, RIGHT12, BUSVOODOO_XVCTL_CHANNEL); // set output so the voltage regulator is set to 2.5V - dac_software_trigger(BUSVOODOO_XVCTL_CHANNEL); // transfer the value to the DAC - dac_enable(BUSVOODOO_XVCTL_CHANNEL); // enable DAC - sleep_ms(5); // let voltage settle - voltage = rail_voltage(BUSVOODOO_XV_CHANNEL); // get xV voltage - // check if it matched desired voltage - if (voltageBUSVOODOO_XV_TEST+0.2) { - printf("xV voltage is highed (%.2fV) than set (%.2fV)\n", voltage, BUSVOODOO_XV_TEST); -#if DEBUG - while (true); -#else - goto error; -#endif - } - dac_disable(BUSVOODOO_XVCTL_CHANNEL); // disable xV control - gpio_clear(GPIO(BUSVOODOO_XVEN_PORT), GPIO(BUSVOODOO_XVEN_PIN)); // disable xV voltage regulator - sleep_ms(1); // let voltage settle - - // check 12V voltage regulator - if (busvoodoo_full) { - gpio_set(GPIO(BUSVOODOO_12VEN_PORT), GPIO(BUSVOODOO_12VEN_PIN)); // disable 12V voltage regulator - sleep_ms(1); // let voltage settle - voltage = rail_voltage(BUSVOODOO_12V_CHANNEL); // get 12V voltage - if (voltage>0.2) { // ensure the output is at 0V when the regulator is not enabled - printf("12V voltage is %.2fV instead of 0V when the regulator is disabled\n", voltage); -#if DEBUG - while (true); -#else - goto error; -#endif - } - gpio_clear(GPIO(BUSVOODOO_12VEN_PORT), GPIO(BUSVOODOO_12VEN_PIN)); // enable 12V voltage regulator - sleep_ms(10); // let the voltage regulator start and voltage settle - voltage = rail_voltage(BUSVOODOO_12V_CHANNEL); // get 12V voltage - // without being driven it should be around the default voltage - if (voltageBUSVOODOO_12V_DEFAULT+0.3) { - printf("12V voltage is higher (%.2fV) than expected (%.2fV) when regulator is enabled\n", voltage, BUSVOODOO_12V_DEFAULT); -#if DEBUG - while (true); -#else - goto error; -#endif - } - - // check if we can control 12V voltage regulator - voltage = rail_voltage(BUSVOODOO_3V3_CHANNEL); // get reference voltage - if (isnan(voltage)) { - printf("can get 3V3 rail voltage"); - goto error; - } - dac_set = BUSVOODOO_12V_SET(BUSVOODOO_12V_TEST)/voltage*4095; // DAC value corresponding to the voltage - dac_load_data_buffer_single(dac_set, RIGHT12, BUSVOODOO_12VCTL_CHANNEL); // set output so the voltage regulator is set to desired output voltage - dac_software_trigger(BUSVOODOO_12VCTL_CHANNEL); // transfer the value to the DAC - dac_enable(BUSVOODOO_12VCTL_CHANNEL); // enable DAC - sleep_ms(10); // let voltage settle - voltage = rail_voltage(BUSVOODOO_12V_CHANNEL); // get 12V voltage - if (voltageBUSVOODOO_12V_TEST+0.3) { - printf("12V voltage is higher (%.2fV) than set (%.2fV)\n", voltage, BUSVOODOO_12V_TEST); -#if DEBUG - while (true); -#else - goto error; -#endif - } - dac_disable(BUSVOODOO_12VCTL_CHANNEL); // disable 12V control - gpio_set(GPIO(BUSVOODOO_12VEN_PORT), GPIO(BUSVOODOO_12VEN_PIN)); // disable 12V voltage regulator - sleep_ms(1); // let voltage settle - } - - // pull all pins down and ensure they are low - for (uint8_t pin=0; pin5.5) { - printf("5V power rail voltage is too high when used to pull up: %.2fV\n", voltage); -#if DEBUG - while (true); -#else - goto error; -#endif - } - for (uint8_t pin=0; pinBUSVOODOO_XV_DEFAULT+0.2) { - printf("xV voltage is higher (%.2fV) than expected (%.2fV) when used to pull up\n", voltage, BUSVOODOO_XV_DEFAULT); -#if DEBUG - while (true); -#else - goto error; -#endif - } - for (uint8_t pin=0; pin0.2) { // wait until pin is shorted to ground - sleep_ms(200); // wait for user to make connection - } - gpio_clear(GPIO(BUSVOODOO_XVCTL_PORT), GPIO(BUSVOODOO_XVCTL_PIN)); // set pin low - gpio_set_mode(GPIO(BUSVOODOO_XVCTL_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUSVOODOO_XVCTL_PIN)); // set xV control pin as output - led_toggle(); // notify user test is almost almost - sleep_ms(200); // wait for voltage to settle an debounce - if (rail_voltage(BUSVOODOO_XV_CHANNEL)>0.2) { - printf(xv_high); -#if DEBUG - while (true); -#else - goto error; -#endif - } - gpio_set_mode(GPIO(BUSVOODOO_XVCTL_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO(BUSVOODOO_XVCTL_PIN)); // set xV control pin back to analog input for DAC - led_toggle(); // notify user test is complete - - // test 5V output on pin 2 - gpio_clear(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // enable Vout - printf("%sI/O pin 2\n", xv_to); - while (rail_voltage(BUSVOODOO_XV_CHANNEL)<0.2) { // wait until pin is connected - sleep_ms(200); // wait for user to make connection - } - gpio_set(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // disable Vout - led_toggle(); // notify user test is almost complete - sleep_ms(200); // wait for voltage to settle and debounce - if (rail_voltage(BUSVOODOO_XV_CHANNEL)>0.2) { - printf(xv_high); -#if DEBUG - while (true); -#else - goto error; -#endif - } - led_toggle(); // notify user test is complete - - // test 3.3V output on pin 3 - gpio_clear(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // enable Vout - printf("%sI/O pin 3\n", xv_to); - while (rail_voltage(BUSVOODOO_XV_CHANNEL)<0.2 || rail_voltage(BUSVOODOO_XV_CHANNEL)>3.5) { // wait until pin is connected - sleep_ms(200); // wait for user to make connection - } - gpio_set(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // disable Vout - led_toggle(); // notify user test is almost complete - sleep_ms(200); // wait for voltage to settle and debounce - if (rail_voltage(BUSVOODOO_XV_CHANNEL)>0.2) { - printf(xv_high); -#if DEBUG - while (true); -#else - goto error; -#endif - } - led_toggle(); // notify user test is complete - - // test I/O pins - for (uint8_t io=1; io<=6; io++) { // test each I/O pin - for (uint8_t pin=0; pin0.2) { - printf(xv_high); -#if DEBUG - while (true); -#else - goto error; -#endif - } - gpio_set_mode(busvoodoo_io_ports[pin], GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, busvoodoo_io_pins[pin]); // set pin back to input - led_toggle(); // notify user test is complete - break; // stop looking for pin - } - } - } - - if (busvoodoo_full) { - // test 12V output on RS/CAN pin 1 - double voltage = rail_voltage(BUSVOODOO_3V3_CHANNEL); // get reference voltage - uint16_t dac_set = BUSVOODOO_12V_SET(5.0)/voltage*4095; // DAC value corresponding to the voltage - dac_load_data_buffer_single(dac_set, RIGHT12, BUSVOODOO_12VCTL_CHANNEL); // set output so the voltage regulator is set to desired output voltage - dac_software_trigger(BUSVOODOO_12VCTL_CHANNEL); // transfer the value to the DAC - dac_enable(BUSVOODOO_12VCTL_CHANNEL); // enable DAC - gpio_clear(GPIO(BUSVOODOO_12VEN_PORT), GPIO(BUSVOODOO_12VEN_PIN)); // enable 12V voltage regulator - printf("%sRS/CAN pin 1\n", xv_to); - while (rail_voltage(BUSVOODOO_XV_CHANNEL)<0.2) { // wait until pin is connected - sleep_ms(200); // wait for user to make connection - } - gpio_set(GPIO(BUSVOODOO_12VEN_PORT), GPIO(BUSVOODOO_12VEN_PIN)); // disable 12V voltage regulator - dac_disable(BUSVOODOO_12VCTL_CHANNEL); // disable 12V control - led_toggle(); // notify user test is almost complete - sleep_ms(200); // wait for voltage to settle (and debounce) - if (rail_voltage(BUSVOODOO_XV_CHANNEL)>0.2) { - printf(xv_high); -#if DEBUG - while (true); -#else - goto error; -#endif - } - led_toggle(); // notify user test is complete - - // test RS-232 port (with itself) - rcc_periph_clock_enable(RCC_GPIO(BUSVOODOO_RS232_EN_PORT)); // enable clock for GPIO domain - gpio_clear(GPIO(BUSVOODOO_RS232_EN_PORT), GPIO(BUSVOODOO_RS232_EN_PIN)); // set low to enable receiver - gpio_set_mode(GPIO(BUSVOODOO_RS232_EN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(BUSVOODOO_RS232_EN_PIN)); // set pin as output (open-drain pulled high to disable receiver) - rcc_periph_clock_enable(RCC_GPIO(BUSVOODOO_RS232_SHDN_PORT)); // enable clock for GPIO domain - gpio_set(GPIO(BUSVOODOO_RS232_SHDN_PORT), GPIO(BUSVOODOO_RS232_SHDN_PIN)); // set high to enable transmitter - gpio_set_mode(GPIO(BUSVOODOO_RS232_SHDN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUSVOODOO_RS232_SHDN_PIN)); // set pin as output (push-pull pulled low to disable transmitter) - rcc_periph_clock_enable(RCC_GPIO(BUSVOODOO_RS232_TX_PORT)); // enable clock for GPIO - gpio_set_mode(GPIO(BUSVOODOO_RS232_TX_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUSVOODOO_RS232_TX_PIN)); // set pin as output (push-pull) - rcc_periph_clock_enable(RCC_GPIO(BUSVOODOO_RS232_RX_PORT)); // enable clock for GPIO - gpio_set_mode(GPIO(BUSVOODOO_RS232_RX_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO(BUSVOODOO_RS232_RX_PIN)); // set pin as input (with pull resistors) - // start by setting low since unconnected (pulled to ground by 3 kO) is considered as high - gpio_clear(GPIO(BUSVOODOO_RS232_TX_PORT), GPIO(BUSVOODOO_RS232_TX_PIN)); // set low - gpio_set(GPIO(BUSVOODOO_RS232_RX_PORT), GPIO(BUSVOODOO_RS232_RX_PIN)); // pull high to avoid false negative - sleep_ms(5); - printf("connect RS/CAN pin 2 to RS/CAN pin 3\n"); - while (gpio_get(GPIO(BUSVOODOO_RS232_RX_PORT), GPIO(BUSVOODOO_RS232_RX_PIN))) { // wait until pin is connected - sleep_ms(200); // wait for user to make connection - } - gpio_set(GPIO(BUSVOODOO_RS232_TX_PORT), GPIO(BUSVOODOO_RS232_TX_PIN)); // set high - gpio_clear(GPIO(BUSVOODOO_RS232_RX_PORT), GPIO(BUSVOODOO_RS232_RX_PIN)); // pull low to avoid false negative - led_toggle(); // notify user test is almost complete - sleep_ms(200); // wait for voltage to settle and debounce - if (!gpio_get(GPIO(BUSVOODOO_RS232_RX_PORT), GPIO(BUSVOODOO_RS232_RX_PIN))) { // check if RX is set low by TX - printf("CAN/RS pin 2 is high while it should be set low by pin 3\n"); -#if DEBUG - while (true); -#else - goto error; -#endif - } - gpio_set_mode(GPIO(BUSVOODOO_RS232_TX_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_RS232_TX_PIN)); // free pin - gpio_set_mode(GPIO(BUSVOODOO_RS232_RX_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_RS232_RX_PIN)); // free pin - led_toggle(); // notify user test is complete - - rcc_periph_clock_enable(RCC_GPIO(BUSVOODOO_RS232_RTS_PORT)); // enable clock for GPIO - gpio_set_mode(GPIO(BUSVOODOO_RS232_RTS_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUSVOODOO_RS232_RTS_PIN)); // set pin as output (push-pull) - rcc_periph_clock_enable(RCC_GPIO(BUSVOODOO_RS232_CTS_PORT)); // enable clock for GPIO - gpio_set_mode(GPIO(BUSVOODOO_RS232_CTS_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO(BUSVOODOO_RS232_CTS_PIN)); // set pin as input (with pull resistors) - // start by setting low since unconnected (pulled to ground by 3 kO) is considered as high - gpio_clear(GPIO(BUSVOODOO_RS232_RTS_PORT), GPIO(BUSVOODOO_RS232_RTS_PIN)); // set low - gpio_set(GPIO(BUSVOODOO_RS232_CTS_PORT), GPIO(BUSVOODOO_RS232_CTS_PIN)); // pull high to avoid false negative - printf("connect RS/CAN pin 4 to RS/CAN pin 5\n"); - while (gpio_get(GPIO(BUSVOODOO_RS232_CTS_PORT), GPIO(BUSVOODOO_RS232_CTS_PIN))) { // wait until pin is connected - sleep_ms(200); // wait for user to make connection - } - gpio_set(GPIO(BUSVOODOO_RS232_RTS_PORT), GPIO(BUSVOODOO_RS232_RTS_PIN)); // set high - gpio_clear(GPIO(BUSVOODOO_RS232_CTS_PORT), GPIO(BUSVOODOO_RS232_CTS_PIN)); // pull low to avoid false negative - led_toggle(); // notify user test is almost complete - sleep_ms(200); // wait for voltage to settle an debounce - if (!gpio_get(GPIO(BUSVOODOO_RS232_CTS_PORT), GPIO(BUSVOODOO_RS232_CTS_PIN))) { // check if CTS is set high by RTS - printf("CAN/RS pin 5 is high while it should be set low by pin 4\n"); -#if DEBUG - while (true); -#else - goto error; -#endif - } - gpio_set_mode(GPIO(BUSVOODOO_RS232_RTS_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_RS232_RTS_PIN)); // free pin - gpio_set_mode(GPIO(BUSVOODOO_RS232_CTS_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_RS232_CTS_PIN)); // free pin - led_toggle(); // notify user test is complete - - gpio_set(GPIO(BUSVOODOO_RS232_EN_PORT), GPIO(BUSVOODOO_RS232_EN_PIN)); // set high to disable receiver - gpio_clear(GPIO(BUSVOODOO_RS232_SHDN_PORT), GPIO(BUSVOODOO_RS232_SHDN_PIN)); // set low to disable transmitter - } - - to_return = true; // all tests passed -#if DEBUG -#else -error: -#endif - safe_state(); // go back to safe state - if (!to_return) { - printf("the test procedure has been aborted for safety reasons\n"); - } - - return to_return; -} - /** process user command * @param[in] str user command string (\0 ended) */ @@ -879,7 +107,9 @@ static void process_command(char* str) // parse command if (0==strcmp(word,"h") || 0==strcmp(word,"help") || 0==strcmp(word,"?")) { printf("available commands:\n"); - printf("led [on|off|toggle]\n"); + printf("l|led [on|off|toggle]\n"); + printf("s|self-test\n"); + printf("p|pin-test\n"); } else if (0==strcmp(word,"l") || 0==strcmp(word,"led")) { word = strtok(NULL,delimiter); if (!word) { @@ -901,6 +131,35 @@ static void process_command(char* str) } else { goto error; } + } else if (0==strcmp(word,"s") || 0==strcmp(word,"self_-test")) { + printf("performing self-test\n"); + printf("remove all cables from connectors and press space to start\n"); + if (wait_space()) { + if (busvoodoo_hiz_test_self()) { // perform self-test + led_blink(0, 1.0); // show blue OK LED + printf("self-test succeeded\n"); // notify user + } else { + led_blink(0.5, 0.5); // show error on LEDs + printf("self-test failed\n"); // notify user + } + } else { + printf("self-test aborted\n"); + } + } else if (0==strcmp(word,"p") || 0==strcmp(word,"pin-test")) { + printf("performing pin test\n"); + printf("test will proceed automatically once the connection is detected\n"); + printf("remove all cables from connectors and press space to start\n"); + if (wait_space()) { + if (busvoodoo_hiz_test_self()) { // perform self-test + led_blink(0, 1.0); // show blue OK LED + printf("pin test succeeded\n"); // notify user + } else { + led_blink(0.5, 0.5); // show error on LEDs + printf("pin test failed\n"); // notify user + } + } else { + printf("pin :test aborted\n"); + } } else { goto error; } @@ -951,161 +210,15 @@ void main(void) #endif */ - // enable all GPIO domains since we use pins on all ports - rcc_periph_clock_enable(RCC_GPIOA); // enable clock for all GPIO domains - rcc_periph_clock_enable(RCC_GPIOB); // enable clock for all GPIO domains - rcc_periph_clock_enable(RCC_GPIOC); // enable clock for all GPIO domains - rcc_periph_clock_enable(RCC_GPIOD); // enable clock for all GPIO domains - safe_state(); // switch off all outputs - + busvoodoo_setup(); // setup BusVoodoo board printf("\nwelcome to BusVoodoo ("); // print welcome message - // check if this BusVoodoo is a full version - rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_12V_CHANNEL)); // enable clock for GPIO domain for 12V channel - gpio_set(ADC12_IN_PORT(BUSVOODOO_12V_CHANNEL), ADC12_IN_PIN(BUSVOODOO_12V_CHANNEL)); // pull ADC 12V high - gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_12V_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, ADC12_IN_PIN(BUSVOODOO_12V_CHANNEL)); // set 12V channel as digital input with pull-up capabilities - // on a full version (fully populated board) the ADC 12V signal will be pulled low - if (gpio_get(ADC12_IN_PORT(BUSVOODOO_12V_CHANNEL), ADC12_IN_PIN(BUSVOODOO_12V_CHANNEL))) { // check is ADC 12V is pulled low - busvoodoo_full = false; - printf("light"); - } else { - busvoodoo_full = true; + if (busvoodoo_full) { printf("full"); + } else { + printf("light"); } printf(" version)\n"); - // setup ADC to measure the 5V, 3.3V, xV, and 12V power rails voltages - rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_5V_CHANNEL)); // enable clock for GPIO domain for 5V channel - 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 - rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_3V3_CHANNEL)); // enable clock for GPIO domain for 3.3V channel - 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 - rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_XV_CHANNEL)); // enable clock for GPIO domain for xV channel - gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_XV_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_XV_CHANNEL)); // set xV channel as analogue input for the ADC - rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_12V_CHANNEL)); // enable clock for GPIO domain for 12V channel - gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_12V_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_12V_CHANNEL)); // set 12V channel as analogue input for the ADC - rcc_periph_clock_enable(RCC_ADC1); // enable clock for ADC domain - adc_off(ADC1); // switch off ADC while configuring it - adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC); // use 28.5 cycles to sample (long enough to be stable) - adc_enable_temperature_sensor(ADC1); // enable internal voltage reference - adc_enable_external_trigger_regular(ADC1, ADC_CR2_EXTSEL_SWSTART); // use software trigger to start conversion - uint8_t channels[] = {ADC_CHANNEL17, ADC_CHANNEL(BUSVOODOO_5V_CHANNEL), ADC_CHANNEL(BUSVOODOO_3V3_CHANNEL), ADC_CHANNEL(BUSVOODOO_XV_CHANNEL), ADC_CHANNEL(BUSVOODOO_12V_CHANNEL)}; // voltages to convert: internal, 5V, 3.3V, xV, 12V - adc_set_regular_sequence(ADC1, LENGTH(channels), channels); // set channels to convert - adc_enable_discontinuous_mode_regular(ADC1, LENGTH(channels)); // convert all channels - adc_power_on(ADC1); // switch on ADC - sleep_us(1); // wait t_stab for the ADC to stabilize - adc_reset_calibration(ADC1); // remove previous non-calibration - adc_calibration(ADC1); // calibrate ADC for less accuracy errors - - // setup DAC to control xV and 12V voltage outputs - gpio_set_mode(GPIO(BUSVOODOO_XVCTL_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO(BUSVOODOO_XVCTL_PIN)); // set xV pin as analog (the DAC will use it as output) - rcc_periph_clock_enable(RCC_DAC); // enable clock for DAC domain - dac_disable(BUSVOODOO_XVCTL_CHANNEL); // disable output to configure it properly - dac_buffer_enable(BUSVOODOO_XVCTL_CHANNEL); // enable output buffer to be able to drive larger loads (should be per default) - if (busvoodoo_full) { - gpio_set_mode(GPIO(BUSVOODOO_12VCTL_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO(BUSVOODOO_12VCTL_PIN)); // set 12V pin as analog (the DAC will use it as output) - dac_disable(BUSVOODOO_12VCTL_CHANNEL); // disable output to configure it properly - dac_buffer_enable(BUSVOODOO_12VCTL_CHANNEL); // enable output buffer to be able to drive larger loads (should be per default) - } - dac_set_trigger_source(DAC_CR_TSEL1_SW); // use software to trigger the voltage change - dac_set_trigger_source(DAC_CR_TSEL2_SW); // use software to trigger the voltage change - -/* - printf("testing OLED screen\n"); - i2c_master_setup(false); - const uint8_t oled_init[] = { - 0x00, // control byte: continuous (multiple byes), command - 0xae, // Set Display ON/OFF: OFF - // hardware configuration - 0xa8, 0x3f, // Set Multiplex Ratio: 64 - 0xd3, 0x00, // Set Display Offset: 0 - 0xa1, // Set Segment Re-map: column address 0 is mapped to SEG127 - 0xc8, // Set COM Output Scan Direction: normal mode (RESET) Scan from COM[N-1] to COM[0] - 0xda, 0x12, // Set COM Pins Hardware Configuration: Alternative COM pin configuration, Disable COM Left/Right remap - 0x40, // Set Display Start Line: start line register from 0 - // fundamental commands - 0x81, 0xff, // Set Contrast Control: 256 - 0xa6, // Set Normal/Inverse Display: Normal display (RESET) - // Timing & Driving Scheme Setting - 0xd5, 0xf0, // Set Display Clock Divide Ratio/Oscillator Frequency: Divide ratio=129, F_OSC=1 - 0xd9, 0x22, // Set Pre-charge Period: Phase 1=2 DCLK, Phase 2=2DCLK - 0xdb, 0x20, // Set V_COMH Deselect Level: ~0.77xV_CC - // Charge Pump - 0x8d, 0x14, // Charge Pump Setting: Enable Charge Pump - // Addressing Setting - 0x20, 0x00 // Set Memory Addressing Mode: Horizontal Addressing Mode - }; - i2c_master_write(0x3c, oled_init, LENGTH(oled_init), NULL, 0); - const uint8_t oled_entire_display_on[] = { - 0x80, // control byte: no continuation, command - 0xa5 // Entire Display ON: Entire display ON Output ignores RAM content - }; - i2c_master_write(0x3c, oled_entire_display_on, LENGTH(oled_entire_display_on), NULL, 0); - const uint8_t oled_display_on[] = { - 0x80, // control byte: no continuation, command - 0xaf, // Set Display ON/OFF: ON - }; - i2c_master_write(0x3c, oled_display_on, LENGTH(oled_display_on), NULL, 0); - sleep_ms(200); - const uint8_t oled_entire_display_ram[] = { - 0x80, // control byte: no continuation, command - 0xa4 // Entire Display ON: Resume to RAM content display - }; - i2c_master_write(0x3c, oled_entire_display_ram, LENGTH(oled_entire_display_ram), NULL, 0); - const uint8_t oled_start_page[] = { - 0x00, // control byte: continuous (multiple byes), command - 0xb0, // Set Page Start Address for Page Addressing Mode: PAGE0 - 0x00, // Set Lower Column Start Address for Page Addressing Mode: 0 - 0x10 // Set Higher Column Start Address for Page Addressing Mode: 0 - }; - i2c_master_write(0x3c, oled_start_page, LENGTH(oled_start_page), NULL, 0); - const uint8_t oled_data[] = {0x40, 0, 254, 254, 0, 0, 0, 0, 0, 0, 254, 254, 0, 0, 224, 240, 56, 28, 14, 14, 28, 56, 240, 224, 0, 0, 254, 254, 134, 134, 134, 134, 134, 206, 252, 120, 0, 0, 6, 6, 6, 6, 254, 254, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 254, 254, 6, 6, 6, 6, 0, 0, 30, 62, 112, 224, 192, 192, 224, 112, 62, 30, 0, 0, 254, 254, 134, 134, 134, 134, 134, 206, 252, 120, 0, 0, 30, 62, 112, 224, 192, 192, 224, 112, 62, 30, 0, 0, 31, 63, 112, 96, 96, 96, 96, 112, 63, 31, 0, 0, 127, 127, 6, 6, 6, 6, 6, 6, 127, 127, 0, 0, 127, 127, 1, 3, 7, 15, 29, 57, 112, 96, 0, 0, 0, 0, 0, 0, 127, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 127, 0, 0, 0, 0, 0, 0, 120, 124, 14, 7, 3, 3, 7, 14, 124, 120, 0, 0, 127, 127, 1, 3, 7, 15, 29, 57, 112, 96, 0, 0, 120, 124, 14, 7, 3, 3, 7, 14, 124, 120, 0, 255, 255, 3, 3, 3, 3, 11, 19, 35, 67, 131, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 131, 67, 35, 19, 11, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 132, 72, 48, 48, 72, 132, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 255, 17, 17, 49, 209, 14, 0, 0, 1, 1, 1, 255, 1, 1, 1, 0, 142, 17, 17, 33, 33, 198, 0, 0, 0, 0, 0, 0, 255, 17, 17, 49, 209, 14, 0, 0, 3, 204, 48, 48, 204, 3, 0, 0, 0, 0, 0, 0, 134, 1, 17, 17, 17, 238, 0, 0, 7, 56, 192, 0, 192, 56, 7, 0, 134, 1, 17, 17, 17, 238, 0, 0, 254, 1, 1, 33, 33, 230, 0, 0, 255, 6, 24, 96, 128, 255, 0, 0, 255, 1, 1, 1, 2, 252, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 64, 32, 16, 8, 4, 2, 1, 0, 0, 0, 0, 0, 0, 1, 2, 4, 8, 16, 32, 64, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 2, 2, 2, 2, 1, 0, 0, 1, 2, 2, 2, 1, 3, 0, 0, 3, 0, 0, 0, 1, 3, 0, 0, 3, 2, 2, 2, 1, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 2, 4, 8, 16, 32, 64, 128, 0, 0, 0, 0, 0, 0, 128, 64, 32, 16, 8, 4, 2, 0, 0, 0, 128, 64, 64, 64, 64, 128, 0, 0, 64, 64, 64, 192, 64, 64, 64, 0, 128, 64, 64, 64, 64, 128, 0, 0, 0, 0, 0, 0, 64, 64, 64, 192, 64, 64, 64, 0, 192, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 64, 64, 64, 64, 64, 0, 0, 192, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 64, 33, 18, 12, 12, 18, 33, 64, 128, 0, 0, 0, 0, 0, 0, 0, 0, 127, 128, 128, 128, 128, 97, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 99, 132, 132, 136, 136, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 192, 51, 12, 12, 51, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 195, 36, 24, 24, 36, 195, 0, 0, 1, 14, 48, 192, 48, 14, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 132, 132, 132, 132, 120, 0, 0, 1, 14, 48, 192, 48, 14, 1, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 192, 192, 192, 192, 208, 200, 196, 194, 193, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 193, 194, 196, 200, 208, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 255, 255}; - i2c_master_write(0x3c, oled_data, LENGTH(oled_data), NULL, 0); -*/ - - if (false) { - // perform tests - printf("performing self-test, please follow instructions\n"); - if (!test_self()) { // perform self-test - led_blink(0.5, 0.5); // show error on LEDs - } else { - led_blink(0, 1.0); // show blue OK LED - printf("self-test succeeded\n"); // notify user - } - - printf("performing pin test, please follow instructions\n"); - if (!test_pins()) { // perform external test - led_blink(0.5, 0.5); // show error on LEDs - } else { - led_blink(0, 1.0); // show blue OK LED - printf("pin test succeeded\n"); // notify user - } - } - -/* - printf("testing RS-485 port\n"); - rs485_setup(); -*/ - -/* - printf("testing RS-232 port\n"); - rs232_setup(); -*/ - -/* - // test CAN - gpio_clear(GPIOC, GPIO13); - gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO13); - gpio_set(GPIOB, GPIO9); - gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO9); // CAN TX - gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO8); // CAN RX - gpio_clear(GPIOC, GPIO7); - gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO7); // CAN EN - while (true) { - gpio_toggle(GPIOB, GPIO9); - sleep_ms(100); - } - wait_space(); -*/ - // main loop printf("command input: ready\n"); terminal_prefix = "BV: "; // set terminal prefix diff --git a/lib/busvoodoo_global.c b/lib/busvoodoo_global.c new file mode 100644 index 0000000..2aa8fd8 --- /dev/null +++ b/lib/busvoodoo_global.c @@ -0,0 +1,173 @@ +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +/** BusVoodoo global definitions and methods (code) + * @file busvoodoo_global.c + * @author King Kévin + * @date 2018 + */ + +/* standard libraries */ +#include // standard integer types +#include // math utilities + +/* STM32 (including CM3) libraries */ +#include // general purpose input output library +#include // real-time control clock library +#include // ADC utilities +#include // DAC utilities + +/* own libraries */ +#include "global.h" // board definitions +#include "busvoodoo_global.h" // BusVoodoo definitions + +const char* busvoodoo_io_names[13] = {"I2C_SMBA/SPI_NSS/I2S_WS", "SDIO_CMD", "USART_CTS/SPI_SCK/I2S_CK", "SDIO_D3/UART_RX", "I2C_SDA/USART_RX", "SDIO_D0", "SPI_MOSI/I2S_SD", "SDIO_CK/USART_CK", "I2C_SCL/USART_TX", "SDIO_D1", "I2S_MCK", "USART_RTS/SPI_MISO", "SDIO_D2/UART_TX"}; +const uint32_t busvoodoo_io_ports[13] = {GPIOB, GPIOD, GPIOB, GPIOC, GPIOB, GPIOC, GPIOB, GPIOC, GPIOB, GPIOC, GPIOC, GPIOB, GPIOC}; +const uint32_t busvoodoo_io_pins[13] = {GPIO12, GPIO2, GPIO13, GPIO11, GPIO11, GPIO8, GPIO15, GPIO12, GPIO10, GPIO9, GPIO6, GPIO14, GPIO10}; +const uint8_t busvoodoo_io_groups[13] = {6, 6, 4, 4, 1, 1, 5, 5, 2, 2, 3, 3, 3}; + +bool busvoodoo_full = false; + +void busvoodoo_setup(void) +{ + // enable all GPIO domains since we use pins on all ports + rcc_periph_clock_enable(RCC_GPIOA); // enable clock for all GPIO domains + rcc_periph_clock_enable(RCC_GPIOB); // enable clock for all GPIO domains + rcc_periph_clock_enable(RCC_GPIOC); // enable clock for all GPIO domains + rcc_periph_clock_enable(RCC_GPIOD); // enable clock for all GPIO domains + busvoodoo_safe_state(); // switch off all outputs + + // check if this BusVoodoo is a full version + rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_12V_CHANNEL)); // enable clock for GPIO domain for 12V channel + gpio_set(ADC12_IN_PORT(BUSVOODOO_12V_CHANNEL), ADC12_IN_PIN(BUSVOODOO_12V_CHANNEL)); // pull ADC 12V high + gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_12V_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, ADC12_IN_PIN(BUSVOODOO_12V_CHANNEL)); // set 12V channel as digital input with pull-up capabilities + // on a full version (fully populated board) the ADC 12V signal will be pulled low + if (gpio_get(ADC12_IN_PORT(BUSVOODOO_12V_CHANNEL), ADC12_IN_PIN(BUSVOODOO_12V_CHANNEL))) { // check is ADC 12V is pulled low + busvoodoo_full = false; + } else { + busvoodoo_full = true; + } + + // setup ADC to measure the 5V, 3.3V, xV, and 12V power rails voltages + rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_5V_CHANNEL)); // enable clock for GPIO domain for 5V channel + 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 + rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_3V3_CHANNEL)); // enable clock for GPIO domain for 3.3V channel + 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 + rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_XV_CHANNEL)); // enable clock for GPIO domain for xV channel + gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_XV_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_XV_CHANNEL)); // set xV channel as analogue input for the ADC + rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_12V_CHANNEL)); // enable clock for GPIO domain for 12V channel + gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_12V_CHANNEL), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, ADC12_IN_PIN(BUSVOODOO_12V_CHANNEL)); // set 12V channel as analogue input for the ADC + rcc_periph_clock_enable(RCC_ADC1); // enable clock for ADC domain + adc_off(ADC1); // switch off ADC while configuring it + adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC); // use 28.5 cycles to sample (long enough to be stable) + adc_enable_temperature_sensor(ADC1); // enable internal voltage reference + adc_enable_external_trigger_regular(ADC1, ADC_CR2_EXTSEL_SWSTART); // use software trigger to start conversion + uint8_t channels[] = {ADC_CHANNEL17, ADC_CHANNEL(BUSVOODOO_5V_CHANNEL), ADC_CHANNEL(BUSVOODOO_3V3_CHANNEL), ADC_CHANNEL(BUSVOODOO_XV_CHANNEL), ADC_CHANNEL(BUSVOODOO_12V_CHANNEL)}; // voltages to convert: internal, 5V, 3.3V, xV, 12V + adc_set_regular_sequence(ADC1, LENGTH(channels), channels); // set channels to convert + adc_enable_discontinuous_mode_regular(ADC1, LENGTH(channels)); // convert all channels + adc_power_on(ADC1); // switch on ADC + sleep_us(1); // wait t_stab for the ADC to stabilize + adc_reset_calibration(ADC1); // remove previous non-calibration + adc_calibration(ADC1); // calibrate ADC for less accuracy errors + + // setup DAC to control xV and 12V voltage outputs + gpio_set_mode(GPIO(BUSVOODOO_XVCTL_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO(BUSVOODOO_XVCTL_PIN)); // set xV pin as analog (the DAC will use it as output) + rcc_periph_clock_enable(RCC_DAC); // enable clock for DAC domain + dac_disable(BUSVOODOO_XVCTL_CHANNEL); // disable output to configure it properly + dac_buffer_enable(BUSVOODOO_XVCTL_CHANNEL); // enable output buffer to be able to drive larger loads (should be per default) + if (busvoodoo_full) { + gpio_set_mode(GPIO(BUSVOODOO_12VCTL_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO(BUSVOODOO_12VCTL_PIN)); // set 12V pin as analog (the DAC will use it as output) + dac_disable(BUSVOODOO_12VCTL_CHANNEL); // disable output to configure it properly + dac_buffer_enable(BUSVOODOO_12VCTL_CHANNEL); // enable output buffer to be able to drive larger loads (should be per default) + } + dac_set_trigger_source(DAC_CR_TSEL1_SW); // use software to trigger the voltage change + dac_set_trigger_source(DAC_CR_TSEL2_SW); // use software to trigger the voltage change +} + +void busvoodoo_safe_state(void) +{ + // disable voltage outputs + gpio_set(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // disable 5V and 3.3V output on connector + 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) + gpio_clear(GPIO(BUSVOODOO_XVEN_PORT), GPIO(BUSVOODOO_XVEN_PIN)); // disable xV voltage regulator + gpio_set_mode(GPIO(BUSVOODOO_XVEN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUSVOODOO_XVEN_PIN)); // set pin as output (push-pull, pulled low for safety) + gpio_set(GPIO(BUSVOODOO_12VEN_PORT), GPIO(BUSVOODOO_12VEN_PIN)); // disable 12V voltage regulator + gpio_set_mode(GPIO(BUSVOODOO_12VEN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(BUSVOODOO_12VEN_PIN)); // set pin as output (open-drain pulled high to disable the pMOS) + + // set DAC channel back to analog + gpio_set_mode(GPIO(BUSVOODOO_XVCTL_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO(BUSVOODOO_XVCTL_PIN)); // set xV pin as analog + gpio_set_mode(GPIO(BUSVOODOO_12VCTL_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO(BUSVOODOO_12VCTL_PIN)); // set 12V pin as analog + + // disable embedded pull-ups + 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) + gpio_set(GPIO(BUSVOODOO_5VPULLUP_PORT), GPIO(BUSVOODOO_5VPULLUP_PIN)); // set pin high to disable 5V embedded pull-up + 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) + gpio_set(GPIO(BUSVOODOO_OEPULLUP_PORT), GPIO(BUSVOODOO_OEPULLUP_PIN)); // set pin high to disable embedded pull-up bus switch + 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) + + // disable all signal I/O outputs + for (uint8_t pin=0; pin. + * + */ +/** BusVoodoo global definitions and methods (API) + * @file busvoodoo_global.h + * @author King Kévin + * @date 2018 + */ + +/** @defgroup busvoodoo_voltages pin to control voltage regulators and pull-ups definitions + * @{ + */ +#define BUSVOODOO_5VPULLUP_PORT B /**< 5V pull-up enable pin (active low) */ +#define BUSVOODOO_5VPULLUP_PIN 4 /**< 5V pull-up enable pin (active low) */ +#define BUSVOODOO_OEPULLUP_PORT A /**< bus switch output enable pin to enable embedded pull-ups (active low) */ +#define BUSVOODOO_OEPULLUP_PIN 15 /**< bus switch output enable pin to enable embedded pull-ups (active low) */ +#define BUSVOODOO_XVEN_PORT A /**< xV enable pin (active high) */ +#define BUSVOODOO_XVEN_PIN 6 /**< xV enable pin (active high) */ +#define BUSVOODOO_12VEN_PORT A /**< 12V enable pin (active low) */ +#define BUSVOODOO_12VEN_PIN 7 /**< 12V enable pin (active low) */ +#define BUSVOODOO_VOUTEN_PORT B /**< voltage output (5V and 3.3V) enable pin (active low) */ +#define BUSVOODOO_VOUTEN_PIN 3 /**< voltage output (5V and 3.3V) enable pin (active low) */ +/** @} */ + +/** @defgroup busvoodoo_adc ADC inputs to measure voltages from voltage regulators + * @{ + */ +#define BUSVOODOO_3V3_CHANNEL 12 /**< ADC channel to measure 5V rail */ +#define BUSVOODOO_5V_CHANNEL 9 /**< ADC channel to measure 3.3V rail */ +#define BUSVOODOO_XV_CHANNEL 11 /**< ADC channel to measure xV rail */ +#define BUSVOODOO_12V_CHANNEL 15 /**< ADC channel to measure 12V rail */ +/** @} */ + +/** @defgroup busvoodoo_dac DAC output to set voltages of voltage regulators + * @{ + */ +#define BUSVOODOO_XVCTL_PORT A /**< pin to control xV output voltage */ +#define BUSVOODOO_XVCTL_PIN 4 /**< pin to control xV output voltage */ +#define BUSVOODOO_XVCTL_CHANNEL CHANNEL_1 /**< DAC channel to control xV output voltage */ +#define BUSVOODOO_XV_DEFAULT (0.8*(1+30.0/10.0)) /**< default (when not driven) xV voltage regulator output voltage based on R1 and R2 */ +#define BUSVOODOO_XV_TEST 2.5 /**< target xV output voltage to test if we can set control the xV voltage regulator */ +#define BUSVOODOO_XV_SET(x) ((0.8*(1+30.0/10.0)-x)*(10.0/30.0)+0.8) /**< voltage to output for the DAC to set the desired xV output voltage (based on resistor values on the xV adjust pins and xV voltage reference) */ +#define BUSVOODOO_12VCTL_PORT A /**< pin to control 12V output voltage */ +#define BUSVOODOO_12VCTL_PIN 5 /**< pin to control 12V output voltage */ +#define BUSVOODOO_12VCTL_CHANNEL CHANNEL_2 /**< DAC channel to control 12V output voltage */ +#define BUSVOODOO_12V_DEFAULT (1.25*(1+100.0/10.0)) /**< default (when not driven) 12V voltage regulator output voltage based on R1 and R2 */ +#define BUSVOODOO_12V_TEST 12.0 /**< target 12V output voltage to test if we can set control the 12V voltage regulator */ +#define BUSVOODOO_12V_SET(x) ((1.25*(1+100.0/10.0)-x)*(10.0/100.0)+1.25) /**< voltage to output for the DAC to set the desired +12V output voltage (based on resistor values on the 12V adjust pins and 12V voltage reference) */ +/** @} */ + +/** @defgroup busvoodoo_rs232 RS-232 transceiver connection definition + * @{ + */ +#define BUSVOODOO_RS232_EN_PORT B /**< RS-232 pin to enable receiver (active low, pulled up) */ +#define BUSVOODOO_RS232_EN_PIN 5 /**< RS-232 pin to enable receiver (active low, pulled up) */ +#define BUSVOODOO_RS232_SHDN_PORT C /**< RS-232 pin to enable transmitter (active high, pulled low) */ +#define BUSVOODOO_RS232_SHDN_PIN 15 /**< RS-232 pin to enable transmitter (active high, pulled low) */ +#define BUSVOODOO_RS232_RTS_PORT A /**< RS-232 Request-To-Send output pin */ +#define BUSVOODOO_RS232_RTS_PIN 1 /**< RS-232 Request-To-Send output pin */ +#define BUSVOODOO_RS232_CTS_PORT A /**< RS-232 Clear-To-Send input pin */ +#define BUSVOODOO_RS232_CTS_PIN 0 /**< RS-232 Clear-To-Send input pin */ +#define BUSVOODOO_RS232_TX_PORT A /**< RS-232 Transmit output pin */ +#define BUSVOODOO_RS232_TX_PIN 2 /**< RS-232 Transmit output pin */ +#define BUSVOODOO_RS232_RX_PORT A /**< RS-232 Receive input pin */ +#define BUSVOODOO_RS232_RX_PIN 3 /**< RS-232 Receive input pin */ +/** @} */ + +/** @defgroup busvoodoo_can CAN transceiver connection definition + * @{ + */ +#define BUSVOODOO_CAN_EN_PORT C /**< CAN pin to enable transceiver (active high, pulled low) */ +#define BUSVOODOO_CAN_EN_PIN 14 /**< CAN pin to enable transceiver (active high, pulled low) */ +#define BUSVOODOO_CAN_S_PORT C /**< CAN pin to set to silent mode (active low, pulled high) */ +#define BUSVOODOO_CAN_S_PIN 13 /**< CAN pin to set to silent mode (active low, pulled high) */ +#define BUSVOODOO_CAN_TX_PORT B /**< CAN Transmit output pin */ +#define BUSVOODOO_CAN_TX_PIN 9 /**< CAN Transmit output pin */ +#define BUSVOODOO_CAN_RX_PORT B /**< CAN Receive input pin */ +#define BUSVOODOO_CAN_RX_PIN 8 /**< CAN Receive input pin */ +/** @} */ + +/** @defgroup busvoodoo_io I/O connector pin definition + * @{ + */ +extern const char* busvoodoo_io_names[13]; /**< I/O individual signal names */ +extern const uint32_t busvoodoo_io_ports[13]; /**< port of individual signals */ +extern const uint32_t busvoodoo_io_pins[13]; /**< pin of individual signals */ +extern const uint8_t busvoodoo_io_groups[13]; /**< which I/O pin (group) does the signal belong to */ +/** @} */ + +/** is the BusVoodoo board fully populated (with 12V voltage regulator, RS-232, RS-485, CAN transceiver on the back side) */ +extern bool busvoodoo_full; + +/** setup BusVoodoo board */ +void busvoodoo_setup(void); +/** set safe state by disabling all outputs */ +void busvoodoo_safe_state(void); +/** read power rail voltage + * @param[in] channel which ADC channel to read voltage from + * @return voltage of NaN if channel is invalid + */ +float busvoodoo_rail_voltage(uint8_t channel); + diff --git a/lib/busvoodoo_hiz.c b/lib/busvoodoo_hiz.c new file mode 100644 index 0000000..909612a --- /dev/null +++ b/lib/busvoodoo_hiz.c @@ -0,0 +1,633 @@ +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +/** BusVoodoo high impedance (HiZ) default mode (code) + * @file busvoodoo_hiz.h + * @author King Kévin + * @date 2018 + */ +/* standard libraries */ +#include // standard integer types +#include // math utilities + +/* STM32 (including CM3) libraries */ +#include // general purpose input output library +#include // real-time control clock library +#include // debug utilities +#include // design utilities +#include // DAC utilities + +/* own libraries */ +#include "global.h" // board definitions +#include "print.h" // printing utilities +#include "busvoodoo_global.h" // BusVoodoo definitions +#include "busvoodoo_hiz.h" // own definitions + +bool busvoodoo_hiz_test_self(void) +{ + bool to_return = false; // success of the self-test + busvoodoo_safe_state(); // start from a safe state + + // get device information + // get device identifier (DEV_ID) + // 0x412: low-density, 16-32 kB flash + // 0x410: medium-density, 64-128 kB flash + // 0x414: high-density, 256-512 kB flash + // 0x430: XL-density, 768-1024 kB flash + // 0x418: connectivity + if (0==(DBGMCU_IDCODE&DBGMCU_IDCODE_DEV_ID_MASK)) { + printf("device identifier not set: this is probably a defective micro-controller\n"); + } else if (0x414!=(DBGMCU_IDCODE&DBGMCU_IDCODE_DEV_ID_MASK)) { + printf("this (DEV_ID=%03x) is not a high-density device: a wrong micro-controller might have been used\n", (DBGMCU_IDCODE&DBGMCU_IDCODE_DEV_ID_MASK)); + } + // ensure flash size is ok + if (0xffff==DESIG_FLASH_SIZE) { + printf("unknown flash size: this is probably a defective micro-controller\n"); + } + + // check 5V power rail + float voltage = busvoodoo_rail_voltage(BUSVOODOO_5V_CHANNEL); // get 5V power rail voltage + if (voltage<4.0) { + printf("5V power rail voltage is too low: %.2fV\n", voltage); +#if DEBUG + while (true); +#else + goto error; +#endif + } else if (voltage>5.5) { + printf("5V power rail voltage is too high: %.2fV\n", voltage); +#if DEBUG + while (true); +#else + goto error; +#endif + } + + // check 3.3V power rail + voltage = busvoodoo_rail_voltage(BUSVOODOO_3V3_CHANNEL); // get 3.3V power rail voltage + if (voltage<3.0) { + printf("3.3V power rail voltage is too low: %.2fV\n", voltage); +#if DEBUG + while (true); +#else + goto error; +#endif + } else if (voltage>3.6) { + printf("3.3V power rail voltage is too high: %.2fV\n", voltage); +#if DEBUG + while (true); +#else + goto error; +#endif + } + + // test 5V and 3.3V outputs + gpio_clear(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // enable Vout + sleep_ms(1); // wait a bit for voltage to settle + voltage = busvoodoo_rail_voltage(BUSVOODOO_5V_CHANNEL); // get 5V power rail voltage + if (voltage<4.0) { + printf("5V power rail voltage is too low when 5V output is enabled: %.2fV\n", voltage); +#if DEBUG + while (true); +#else + goto error; +#endif + } else if (voltage>5.5) { + printf("5V power rail voltage is too high when 5V output is enabled: %.2fV\n", voltage); +#if DEBUG + while (true); +#else + goto error; +#endif + } + voltage = busvoodoo_rail_voltage(BUSVOODOO_3V3_CHANNEL); // get 3.3V power rail voltage + if (voltage<3.0) { + printf("3.3V power rail voltage is too low when 3V3 output is enabled: %.2fV\n", voltage); +#if DEBUG + while (true); +#else + goto error; +#endif + } else if (voltage>3.6) { + printf("3.3V power rail voltage is too high when 3V3 is enabled: %.2fV\n", voltage); +#if DEBUG + while (true); +#else + goto error; +#endif + } + gpio_set(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // disable Vout + + // check xV voltage regulator + gpio_clear(GPIO(BUSVOODOO_XVEN_PORT), GPIO(BUSVOODOO_XVEN_PIN)); // disable xV voltage regulator + sleep_ms(1); // let voltage settle + voltage = busvoodoo_rail_voltage(BUSVOODOO_XV_CHANNEL); // get xV voltage + if (voltage>0.2) { // ensure the output is at 0V when the regulator is not enabled + printf("xV voltage is %.2fV instead of 0V when the regulator is disabled\n", voltage); +#if DEBUG + while (true); +#else + goto error; +#endif + } + gpio_set(GPIO(BUSVOODOO_XVEN_PORT), GPIO(BUSVOODOO_XVEN_PIN)); // enable xV voltage regulator + sleep_ms(5); // let the voltage regulator start and voltage settle + voltage = busvoodoo_rail_voltage(BUSVOODOO_XV_CHANNEL); // get xV voltage + // without being driven it should be around the default voltage + if (voltageBUSVOODOO_XV_DEFAULT+0.2) { + printf("xV voltage is higher (%.2fV) than expected (%.2fV) when the regulator is enabled\n", voltage, BUSVOODOO_XV_DEFAULT); +#if DEBUG + while (true); +#else + goto error; +#endif + } + + // check if we can control xV + voltage = busvoodoo_rail_voltage(BUSVOODOO_3V3_CHANNEL); // get reference voltage + if (isnan(voltage)) { + printf("can get 3V3 rail voltage"); + goto error; + } + uint16_t dac_set = BUSVOODOO_XV_SET(BUSVOODOO_XV_TEST)/voltage*4095; // DAC value corresponding to the voltage + dac_load_data_buffer_single(dac_set, RIGHT12, BUSVOODOO_XVCTL_CHANNEL); // set output so the voltage regulator is set to 2.5V + dac_software_trigger(BUSVOODOO_XVCTL_CHANNEL); // transfer the value to the DAC + dac_enable(BUSVOODOO_XVCTL_CHANNEL); // enable DAC + sleep_ms(5); // let voltage settle + voltage = busvoodoo_rail_voltage(BUSVOODOO_XV_CHANNEL); // get xV voltage + // check if it matched desired voltage + if (voltageBUSVOODOO_XV_TEST+0.2) { + printf("xV voltage is highed (%.2fV) than set (%.2fV)\n", voltage, BUSVOODOO_XV_TEST); +#if DEBUG + while (true); +#else + goto error; +#endif + } + dac_disable(BUSVOODOO_XVCTL_CHANNEL); // disable xV control + gpio_clear(GPIO(BUSVOODOO_XVEN_PORT), GPIO(BUSVOODOO_XVEN_PIN)); // disable xV voltage regulator + sleep_ms(1); // let voltage settle + + // check 12V voltage regulator + if (busvoodoo_full) { + gpio_set(GPIO(BUSVOODOO_12VEN_PORT), GPIO(BUSVOODOO_12VEN_PIN)); // disable 12V voltage regulator + sleep_ms(1); // let voltage settle + voltage = busvoodoo_rail_voltage(BUSVOODOO_12V_CHANNEL); // get 12V voltage + if (voltage>0.2) { // ensure the output is at 0V when the regulator is not enabled + printf("12V voltage is %.2fV instead of 0V when the regulator is disabled\n", voltage); +#if DEBUG + while (true); +#else + goto error; +#endif + } + gpio_clear(GPIO(BUSVOODOO_12VEN_PORT), GPIO(BUSVOODOO_12VEN_PIN)); // enable 12V voltage regulator + sleep_ms(10); // let the voltage regulator start and voltage settle + voltage = busvoodoo_rail_voltage(BUSVOODOO_12V_CHANNEL); // get 12V voltage + // without being driven it should be around the default voltage + if (voltageBUSVOODOO_12V_DEFAULT+0.3) { + printf("12V voltage is higher (%.2fV) than expected (%.2fV) when regulator is enabled\n", voltage, BUSVOODOO_12V_DEFAULT); +#if DEBUG + while (true); +#else + goto error; +#endif + } + + // check if we can control 12V voltage regulator + voltage = busvoodoo_rail_voltage(BUSVOODOO_3V3_CHANNEL); // get reference voltage + if (isnan(voltage)) { + printf("can get 3V3 rail voltage"); + goto error; + } + dac_set = BUSVOODOO_12V_SET(BUSVOODOO_12V_TEST)/voltage*4095; // DAC value corresponding to the voltage + dac_load_data_buffer_single(dac_set, RIGHT12, BUSVOODOO_12VCTL_CHANNEL); // set output so the voltage regulator is set to desired output voltage + dac_software_trigger(BUSVOODOO_12VCTL_CHANNEL); // transfer the value to the DAC + dac_enable(BUSVOODOO_12VCTL_CHANNEL); // enable DAC + sleep_ms(10); // let voltage settle + voltage = busvoodoo_rail_voltage(BUSVOODOO_12V_CHANNEL); // get 12V voltage + if (voltageBUSVOODOO_12V_TEST+0.3) { + printf("12V voltage is higher (%.2fV) than set (%.2fV)\n", voltage, BUSVOODOO_12V_TEST); +#if DEBUG + while (true); +#else + goto error; +#endif + } + dac_disable(BUSVOODOO_12VCTL_CHANNEL); // disable 12V control + gpio_set(GPIO(BUSVOODOO_12VEN_PORT), GPIO(BUSVOODOO_12VEN_PIN)); // disable 12V voltage regulator + sleep_ms(1); // let voltage settle + } + + // pull all pins down and ensure they are low + for (uint8_t pin=0; pin5.5) { + printf("5V power rail voltage is too high when used to pull up: %.2fV\n", voltage); +#if DEBUG + while (true); +#else + goto error; +#endif + } + for (uint8_t pin=0; pinBUSVOODOO_XV_DEFAULT+0.2) { + printf("xV voltage is higher (%.2fV) than expected (%.2fV) when used to pull up\n", voltage, BUSVOODOO_XV_DEFAULT); +#if DEBUG + while (true); +#else + goto error; +#endif + } + for (uint8_t pin=0; pin0.2) { // wait until pin is shorted to ground + sleep_ms(200); // wait for user to make connection + } + gpio_clear(GPIO(BUSVOODOO_XVCTL_PORT), GPIO(BUSVOODOO_XVCTL_PIN)); // set pin low + gpio_set_mode(GPIO(BUSVOODOO_XVCTL_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUSVOODOO_XVCTL_PIN)); // set xV control pin as output + led_toggle(); // notify user test is almost almost + sleep_ms(200); // wait for voltage to settle an debounce + if (busvoodoo_rail_voltage(BUSVOODOO_XV_CHANNEL)>0.2) { + printf(xv_high); +#if DEBUG + while (true); +#else + goto error; +#endif + } + gpio_set_mode(GPIO(BUSVOODOO_XVCTL_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO(BUSVOODOO_XVCTL_PIN)); // set xV control pin back to analog input for DAC + led_toggle(); // notify user test is complete + + // test 5V output on pin 2 + gpio_clear(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // enable Vout + printf("%sI/O pin 2\n", xv_to); + while (busvoodoo_rail_voltage(BUSVOODOO_XV_CHANNEL)<0.2) { // wait until pin is connected + sleep_ms(200); // wait for user to make connection + } + gpio_set(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // disable Vout + led_toggle(); // notify user test is almost complete + sleep_ms(200); // wait for voltage to settle and debounce + if (busvoodoo_rail_voltage(BUSVOODOO_XV_CHANNEL)>0.2) { + printf(xv_high); +#if DEBUG + while (true); +#else + goto error; +#endif + } + led_toggle(); // notify user test is complete + + // test 3.3V output on pin 3 + gpio_clear(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // enable Vout + printf("%sI/O pin 3\n", xv_to); + while (busvoodoo_rail_voltage(BUSVOODOO_XV_CHANNEL)<0.2 || busvoodoo_rail_voltage(BUSVOODOO_XV_CHANNEL)>3.5) { // wait until pin is connected + sleep_ms(200); // wait for user to make connection + } + gpio_set(GPIO(BUSVOODOO_VOUTEN_PORT), GPIO(BUSVOODOO_VOUTEN_PIN)); // disable Vout + led_toggle(); // notify user test is almost complete + sleep_ms(200); // wait for voltage to settle and debounce + if (busvoodoo_rail_voltage(BUSVOODOO_XV_CHANNEL)>0.2) { + printf(xv_high); +#if DEBUG + while (true); +#else + goto error; +#endif + } + led_toggle(); // notify user test is complete + + // test I/O pins + for (uint8_t io=1; io<=6; io++) { // test each I/O pin + for (uint8_t pin=0; pin0.2) { + printf(xv_high); +#if DEBUG + while (true); +#else + goto error; +#endif + } + gpio_set_mode(busvoodoo_io_ports[pin], GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, busvoodoo_io_pins[pin]); // set pin back to input + led_toggle(); // notify user test is complete + break; // stop looking for pin + } + } + } + + if (busvoodoo_full) { + // test 12V output on RS/CAN pin 1 + double voltage = busvoodoo_rail_voltage(BUSVOODOO_3V3_CHANNEL); // get reference voltage + uint16_t dac_set = BUSVOODOO_12V_SET(5.0)/voltage*4095; // DAC value corresponding to the voltage + dac_load_data_buffer_single(dac_set, RIGHT12, BUSVOODOO_12VCTL_CHANNEL); // set output so the voltage regulator is set to desired output voltage + dac_software_trigger(BUSVOODOO_12VCTL_CHANNEL); // transfer the value to the DAC + dac_enable(BUSVOODOO_12VCTL_CHANNEL); // enable DAC + gpio_clear(GPIO(BUSVOODOO_12VEN_PORT), GPIO(BUSVOODOO_12VEN_PIN)); // enable 12V voltage regulator + printf("%sRS/CAN pin 1\n", xv_to); + while (busvoodoo_rail_voltage(BUSVOODOO_XV_CHANNEL)<0.2) { // wait until pin is connected + sleep_ms(200); // wait for user to make connection + } + gpio_set(GPIO(BUSVOODOO_12VEN_PORT), GPIO(BUSVOODOO_12VEN_PIN)); // disable 12V voltage regulator + dac_disable(BUSVOODOO_12VCTL_CHANNEL); // disable 12V control + led_toggle(); // notify user test is almost complete + sleep_ms(200); // wait for voltage to settle (and debounce) + if (busvoodoo_rail_voltage(BUSVOODOO_XV_CHANNEL)>0.2) { + printf(xv_high); +#if DEBUG + while (true); +#else + goto error; +#endif + } + led_toggle(); // notify user test is complete + + // test RS-232 port (with itself) + rcc_periph_clock_enable(RCC_GPIO(BUSVOODOO_RS232_EN_PORT)); // enable clock for GPIO domain + gpio_clear(GPIO(BUSVOODOO_RS232_EN_PORT), GPIO(BUSVOODOO_RS232_EN_PIN)); // set low to enable receiver + gpio_set_mode(GPIO(BUSVOODOO_RS232_EN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(BUSVOODOO_RS232_EN_PIN)); // set pin as output (open-drain pulled high to disable receiver) + rcc_periph_clock_enable(RCC_GPIO(BUSVOODOO_RS232_SHDN_PORT)); // enable clock for GPIO domain + gpio_set(GPIO(BUSVOODOO_RS232_SHDN_PORT), GPIO(BUSVOODOO_RS232_SHDN_PIN)); // set high to enable transmitter + gpio_set_mode(GPIO(BUSVOODOO_RS232_SHDN_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUSVOODOO_RS232_SHDN_PIN)); // set pin as output (push-pull pulled low to disable transmitter) + rcc_periph_clock_enable(RCC_GPIO(BUSVOODOO_RS232_TX_PORT)); // enable clock for GPIO + gpio_set_mode(GPIO(BUSVOODOO_RS232_TX_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUSVOODOO_RS232_TX_PIN)); // set pin as output (push-pull) + rcc_periph_clock_enable(RCC_GPIO(BUSVOODOO_RS232_RX_PORT)); // enable clock for GPIO + gpio_set_mode(GPIO(BUSVOODOO_RS232_RX_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO(BUSVOODOO_RS232_RX_PIN)); // set pin as input (with pull resistors) + // start by setting low since unconnected (pulled to ground by 3 kO) is considered as high + gpio_clear(GPIO(BUSVOODOO_RS232_TX_PORT), GPIO(BUSVOODOO_RS232_TX_PIN)); // set low + gpio_set(GPIO(BUSVOODOO_RS232_RX_PORT), GPIO(BUSVOODOO_RS232_RX_PIN)); // pull high to avoid false negative + sleep_ms(5); + printf("connect RS/CAN pin 2 to RS/CAN pin 3\n"); + while (gpio_get(GPIO(BUSVOODOO_RS232_RX_PORT), GPIO(BUSVOODOO_RS232_RX_PIN))) { // wait until pin is connected + sleep_ms(200); // wait for user to make connection + } + gpio_set(GPIO(BUSVOODOO_RS232_TX_PORT), GPIO(BUSVOODOO_RS232_TX_PIN)); // set high + gpio_clear(GPIO(BUSVOODOO_RS232_RX_PORT), GPIO(BUSVOODOO_RS232_RX_PIN)); // pull low to avoid false negative + led_toggle(); // notify user test is almost complete + sleep_ms(200); // wait for voltage to settle and debounce + if (!gpio_get(GPIO(BUSVOODOO_RS232_RX_PORT), GPIO(BUSVOODOO_RS232_RX_PIN))) { // check if RX is set low by TX + printf("CAN/RS pin 2 is high while it should be set low by pin 3\n"); +#if DEBUG + while (true); +#else + goto error; +#endif + } + gpio_set_mode(GPIO(BUSVOODOO_RS232_TX_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_RS232_TX_PIN)); // free pin + gpio_set_mode(GPIO(BUSVOODOO_RS232_RX_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_RS232_RX_PIN)); // free pin + led_toggle(); // notify user test is complete + + rcc_periph_clock_enable(RCC_GPIO(BUSVOODOO_RS232_RTS_PORT)); // enable clock for GPIO + gpio_set_mode(GPIO(BUSVOODOO_RS232_RTS_PORT), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUSVOODOO_RS232_RTS_PIN)); // set pin as output (push-pull) + rcc_periph_clock_enable(RCC_GPIO(BUSVOODOO_RS232_CTS_PORT)); // enable clock for GPIO + gpio_set_mode(GPIO(BUSVOODOO_RS232_CTS_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO(BUSVOODOO_RS232_CTS_PIN)); // set pin as input (with pull resistors) + // start by setting low since unconnected (pulled to ground by 3 kO) is considered as high + gpio_clear(GPIO(BUSVOODOO_RS232_RTS_PORT), GPIO(BUSVOODOO_RS232_RTS_PIN)); // set low + gpio_set(GPIO(BUSVOODOO_RS232_CTS_PORT), GPIO(BUSVOODOO_RS232_CTS_PIN)); // pull high to avoid false negative + printf("connect RS/CAN pin 4 to RS/CAN pin 5\n"); + while (gpio_get(GPIO(BUSVOODOO_RS232_CTS_PORT), GPIO(BUSVOODOO_RS232_CTS_PIN))) { // wait until pin is connected + sleep_ms(200); // wait for user to make connection + } + gpio_set(GPIO(BUSVOODOO_RS232_RTS_PORT), GPIO(BUSVOODOO_RS232_RTS_PIN)); // set high + gpio_clear(GPIO(BUSVOODOO_RS232_CTS_PORT), GPIO(BUSVOODOO_RS232_CTS_PIN)); // pull low to avoid false negative + led_toggle(); // notify user test is almost complete + sleep_ms(200); // wait for voltage to settle an debounce + if (!gpio_get(GPIO(BUSVOODOO_RS232_CTS_PORT), GPIO(BUSVOODOO_RS232_CTS_PIN))) { // check if CTS is set high by RTS + printf("CAN/RS pin 5 is high while it should be set low by pin 4\n"); +#if DEBUG + while (true); +#else + goto error; +#endif + } + gpio_set_mode(GPIO(BUSVOODOO_RS232_RTS_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_RS232_RTS_PIN)); // free pin + gpio_set_mode(GPIO(BUSVOODOO_RS232_CTS_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUSVOODOO_RS232_CTS_PIN)); // free pin + led_toggle(); // notify user test is complete + + gpio_set(GPIO(BUSVOODOO_RS232_EN_PORT), GPIO(BUSVOODOO_RS232_EN_PIN)); // set high to disable receiver + gpio_clear(GPIO(BUSVOODOO_RS232_SHDN_PORT), GPIO(BUSVOODOO_RS232_SHDN_PIN)); // set low to disable transmitter + } + + to_return = true; // all tests passed +#if DEBUG +#else +error: +#endif + busvoodoo_safe_state(); // go back to safe state + if (!to_return) { + printf("the test procedure has been aborted for safety reasons\n"); + } + + return to_return; +} + diff --git a/lib/busvoodoo_hiz.h b/lib/busvoodoo_hiz.h new file mode 100644 index 0000000..f8d8e3f --- /dev/null +++ b/lib/busvoodoo_hiz.h @@ -0,0 +1,29 @@ +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +/** BusVoodoo high impedance (HiZ) default mode (API) + * @file busvoodoo_hiz.h + * @author King Kévin + * @date 2018 + */ + +/** perform self tests + * @return if self tests passed + */ +bool busvoodoo_hiz_test_self(void); +/** test if signals are soldered correctly to the connector pins + * @return if pin test passed + */ +bool busvoodoo_hiz_test_pins(void); +