/* Copyright 2012-2014 Benjamin Vedder benjamin@vedder.se 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 . */ /* * hw_45.c * * Created on: 19 okt 2014 * Author: benjamin */ #include "hw.h" #ifdef HW_VERSION_45 #include "ch.h" #include "hal.h" #include "stm32f4xx_conf.h" #include "servo.h" #include "commands.h" // Threads static msg_t temp_thread(void *arg); static WORKING_AREA(temp_thread_wa, 1024); // Variables static volatile bool i2c_running = false; static volatile float temp_now = 30.0; // I2C configuration static const I2CConfig i2cfg = { OPMODE_I2C, 100000, FAST_DUTY_CYCLE_2 }; void hw_init_gpio(void) { // GPIO clock enable RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); // LEDs palSetPadMode(GPIOC, 4, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); palSetPadMode(GPIOA, 7, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); // GPIOC (ENABLE_GATE) palSetPadMode(GPIOC, 10, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); DISABLE_GATE(); // GPIOB (DCCAL) palSetPadMode(GPIOB, 12, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); // GPIOA Configuration: Channel 1 to 3 as alternate function push-pull palSetPadMode(GPIOA, 8, PAL_MODE_ALTERNATE(GPIO_AF_TIM1) | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUDR_FLOATING); palSetPadMode(GPIOA, 9, PAL_MODE_ALTERNATE(GPIO_AF_TIM1) | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUDR_FLOATING); palSetPadMode(GPIOA, 10, PAL_MODE_ALTERNATE(GPIO_AF_TIM1) | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUDR_FLOATING); palSetPadMode(GPIOB, 13, PAL_MODE_ALTERNATE(GPIO_AF_TIM1) | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUDR_FLOATING); palSetPadMode(GPIOB, 14, PAL_MODE_ALTERNATE(GPIO_AF_TIM1) | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUDR_FLOATING); palSetPadMode(GPIOB, 15, PAL_MODE_ALTERNATE(GPIO_AF_TIM1) | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_PUDR_FLOATING); // GPIOB (hall sensors) palSetPadMode(GPIOB, 6, PAL_MODE_INPUT_PULLUP); palSetPadMode(GPIOB, 7, PAL_MODE_INPUT_PULLUP); palSetPadMode(GPIOB, 8, PAL_MODE_INPUT_PULLUP); // Fault pin palSetPadMode(GPIOC, 12, PAL_MODE_INPUT_PULLUP); // ADC Pins palSetPadMode(GPIOA, 0, PAL_MODE_INPUT_ANALOG); palSetPadMode(GPIOA, 1, PAL_MODE_INPUT_ANALOG); palSetPadMode(GPIOA, 2, PAL_MODE_INPUT_ANALOG); palSetPadMode(GPIOA, 3, PAL_MODE_INPUT_ANALOG); palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG); palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG); palSetPadMode(GPIOA, 6, PAL_MODE_INPUT_ANALOG); palSetPadMode(GPIOB, 0, PAL_MODE_INPUT_ANALOG); palSetPadMode(GPIOB, 1, PAL_MODE_INPUT_ANALOG); palSetPadMode(GPIOC, 0, PAL_MODE_INPUT_ANALOG); palSetPadMode(GPIOC, 1, PAL_MODE_INPUT_ANALOG); palSetPadMode(GPIOC, 2, PAL_MODE_INPUT_ANALOG); palSetPadMode(GPIOC, 3, PAL_MODE_INPUT_ANALOG); palSetPadMode(GPIOC, 5, PAL_MODE_INPUT_ANALOG); } void hw_setup_adc_channels(void) { // ADC1 regular channels 0, 5, 10, 13 ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2, ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 3, ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_3Cycles); // ADC2 regular channels 1, 6, 11, 15 ADC_RegularChannelConfig(ADC2, ADC_Channel_1, 1, ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC2, ADC_Channel_6, 2, ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC2, ADC_Channel_11, 3, ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC2, ADC_Channel_15, 4, ADC_SampleTime_3Cycles); // ADC3 regular channels 2, 3, 12, 3 ADC_RegularChannelConfig(ADC3, ADC_Channel_2, 1, ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC3, ADC_Channel_3, 2, ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 3, ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC3, ADC_Channel_3, 4, ADC_SampleTime_3Cycles); // Injected channels ADC_InjectedChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_3Cycles); ADC_InjectedChannelConfig(ADC2, ADC_Channel_5, 1, ADC_SampleTime_3Cycles); // Setup i2c temperature sensor here chThdCreateStatic(temp_thread_wa, sizeof(temp_thread_wa), NORMALPRIO, temp_thread, NULL); } void hw_setup_servo_outputs(void) { // Set up GPIO ports RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // Set up servo structures servos[0].gpio = GPIOB; servos[0].pin = 5; servos[0].offset = 0; servos[0].pos = 128; servos[1].gpio = GPIOB; servos[1].pin = 4; servos[1].offset = 0; servos[1].pos = 0; } void hw_start_i2c(void) { i2cAcquireBus(&HW_I2C_DEV); if (!i2c_running) { palSetPadMode(HW_I2C_SCL_PORT, HW_I2C_SCL_PIN, PAL_MODE_ALTERNATE(HW_I2C_GPIO_AF) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_OSPEED_MID1 | PAL_STM32_PUDR_PULLUP); palSetPadMode(HW_I2C_SDA_PORT, HW_I2C_SDA_PIN, PAL_MODE_ALTERNATE(HW_I2C_GPIO_AF) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_OSPEED_MID1 | PAL_STM32_PUDR_PULLUP); i2cStart(&HW_I2C_DEV, &i2cfg); i2c_running = true; } i2cReleaseBus(&HW_I2C_DEV); } void hw_stop_i2c(void) { i2cAcquireBus(&HW_I2C_DEV); if (i2c_running) { palSetPadMode(HW_I2C_SCL_PORT, HW_I2C_SCL_PIN, PAL_MODE_INPUT); palSetPadMode(HW_I2C_SDA_PORT, HW_I2C_SDA_PIN, PAL_MODE_INPUT); i2cStop(&HW_I2C_DEV); i2c_running = false; } i2cReleaseBus(&HW_I2C_DEV); } static msg_t temp_thread(void *arg) { (void)arg; chRegSetThreadName("I2C Temp samp"); uint8_t rxbuf[10]; uint8_t txbuf[10]; msg_t status = RDY_OK; systime_t tmo = MS2ST(5); i2caddr_t temp_addr = 0x48; hw_start_i2c(); chThdSleepMilliseconds(10); for(;;) { if (i2c_running) { txbuf[0] = 0x00; i2cAcquireBus(&HW_I2C_DEV); status = i2cMasterTransmitTimeout(&HW_I2C_DEV, temp_addr, txbuf, 1, rxbuf, 2, tmo); i2cReleaseBus(&HW_I2C_DEV); if (status == RDY_OK){ int16_t tempi = rxbuf[0] << 8 | rxbuf[1]; float temp = (float)tempi; temp /= 128; temp_now = temp; } } chThdSleepMilliseconds(100); } return 0; } float hw45_get_temp(void) { return temp_now; } #endif