rcc_periph_clock_enable(RCC_GPIOA|RCC_GPIOB|RCC_GPIOC|RCC_GPIOD|RCC_AFIO);// enable clock for all GPIO domains and alternate function (for communication)
busvoodoo_safe_state();// put pins in safe state (for common light version)
rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_HV_CHANNEL));// enable clock for GPIO domain for HV channel
gpio_set(ADC12_IN_PORT(BUSVOODOO_HV_CHANNEL),ADC12_IN_PIN(BUSVOODOO_HV_CHANNEL));// pull ADC HV high
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
// on a full version (fully populated board) the ADC HV signal will be pulled low
if(gpio_get(ADC12_IN_PORT(BUSVOODOO_HV_CHANNEL),ADC12_IN_PIN(BUSVOODOO_HV_CHANNEL))){// check is ADC HV is pulled low
rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_HW_REV_CHANNEL));// enable clock for GPIO domain for hardware revision channel
gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_HW_REV_CHANNEL),GPIO_MODE_INPUT,GPIO_CNF_INPUT_ANALOG,ADC12_IN_PIN(BUSVOODOO_HW_REV_CHANNEL));// set hardware revision 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_trev_channels[]={ADC_CHANNEL17,ADC_CHANNEL(BUSVOODOO_HW_REV_CHANNEL)};// voltages to convert: internal, hardware revision
adc_set_regular_sequence(ADC1,LENGTH(rev_channels),rev_channels);// set channels to convert
adc_enable_discontinuous_mode_regular(ADC1,LENGTH(rev_channels));// convert all channels
adc_power_on(ADC1);// switch on ADC
sleep_us(1);// wait t_stab for the ADC to stabilize
adc_calibration(ADC1);// calibrate ADC for less accuracy errors
adc_start_conversion_regular(ADC1);// start conversion to get first voltage
uint16_tchannels[LENGTH(rev_channels)]={0};// to store the values measured on the channels
for(uint8_tchannel_i=0;channel_i<LENGTH(channels);channel_i++){// get all conversions
while(!adc_eoc(ADC1));// wait until conversion finished
channels[channel_i]=adc_read_regular(ADC1);// read voltage value (clears flag)
}
floatrevision_voltage=channels[1]*1.2/channels[0];// calculate voltage
// find out revision of the board
gpio_set_mode(GPIO(BUSVOODOO_HW_REV_PORT),GPIO_MODE_INPUT,GPIO_CNF_INPUT_PULL_UPDOWN,GPIO(BUSVOODOO_HW_REV_PIN));// use pull up and down to check if a voltage divider is present on the pin
gpio_set(GPIO(BUSVOODOO_HW_REV_PORT),GPIO(BUSVOODOO_HW_REV_PIN));// pull up
boolrev_up=(0!=gpio_get(GPIO(BUSVOODOO_HW_REV_PORT),GPIO(BUSVOODOO_HW_REV_PIN)));// check if the signal is still up
gpio_clear(GPIO(BUSVOODOO_HW_REV_PORT),GPIO(BUSVOODOO_HW_REV_PIN));// pull down
boolrev_down=(0==gpio_get(GPIO(BUSVOODOO_HW_REV_PORT),GPIO(BUSVOODOO_HW_REV_PIN)));// check if the signal is still down
gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_HW_REV_CHANNEL),GPIO_MODE_INPUT,GPIO_CNF_INPUT_ANALOG,ADC12_IN_PIN(BUSVOODOO_HW_REV_CHANNEL));// put back to analog input
// get revision
if(rev_up&&rev_down){// no voltage divider on pin
busvoodoo_revision=18;// the pin is floating only for revision 18
}else{// voltage divider on pin
for(uint8_ti=0;i<LENGTH(busvoodoo_revision_numbers)&&i<LENGTH(busvoodoo_revision_voltages);i++){// go through expected revision voltages
if(revision_voltage>busvoodoo_revision_voltages[i]-0.2&&revision_voltage<busvoodoo_revision_voltages[i]+0.2){// verify if voltage matches
busvoodoo_revision=busvoodoo_revision_numbers[i];// remember revision number for matching voltage
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_LV_CHANNEL));// enable clock for GPIO domain for LV channel
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
rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_HV_CHANNEL));// enable clock for GPIO domain for HV channel
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
rcc_periph_clock_enable(RCC_ADC12_IN(BUSVOODOO_HW_REV_CHANNEL));// enable clock for GPIO domain for hardware revision channel
gpio_set_mode(ADC12_IN_PORT(BUSVOODOO_HW_REV_CHANNEL),GPIO_MODE_INPUT,GPIO_CNF_INPUT_ANALOG,ADC12_IN_PIN(BUSVOODOO_HW_REV_CHANNEL));// set hardware revision channel as analogue input for the ADC
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)
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)
dac_disable(BUSVOODOO_HVCTL_CHANNEL);// disable output to configure it properly
dac_buffer_enable(BUSVOODOO_HVCTL_CHANNEL);// enable output buffer to be able to drive larger loads (should be per default)
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
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)
timer_set_period(TIM(BUSVOODOO_LED_TIMER),0xffff);// set period to maximum
nvic_enable_irq(NVIC_TIM_IRQ(BUSVOODOO_LED_TIMER));// enable interrupts for this timer
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_LVEN_PORT),GPIO(BUSVOODOO_LVEN_PIN));// disable LV voltage regulator
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)
gpio_set(GPIO(BUSVOODOO_HVEN_PORT),GPIO(BUSVOODOO_HVEN_PIN));// disable HV voltage regulator
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)
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)
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
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
// disable RS-485 signals (RS and TX are shared with RS-232)
gpio_set(GPIO(BUSVOODOO_RS485_RE_PORT),GPIO(BUSVOODOO_RS485_RE_PIN));// set high to disable receiver
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
gpio_clear(GPIO(BUSVOODOO_RS485_DE_PORT),GPIO(BUSVOODOO_RS485_DE_PIN));// set low to disable transmitter
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
gpio_set_mode(GPIO(BUSVOODOO_CAN_TX_PORT),GPIO_MODE_INPUT,GPIO_CNF_INPUT_FLOAT,GPIO(BUSVOODOO_CAN_TX_PIN));// set pin to floating
gpio_set_mode(GPIO(BUSVOODOO_CAN_RX_PORT),GPIO_MODE_INPUT,GPIO_CNF_INPUT_FLOAT,GPIO(BUSVOODOO_CAN_RX_PIN));// set pin to floating
gpio_set(GPIO(BUSVOODOO_CAN_EN_PORT),GPIO(BUSVOODOO_CAN_EN_PIN));// set high to power off transceiver
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