diff --git a/latest/Firmware/Transponder/Inc/bsp/bsp.hpp b/latest/Firmware/Transponder/Inc/bsp/bsp.hpp index 467be38..20eb5d9 100644 --- a/latest/Firmware/Transponder/Inc/bsp/bsp.hpp +++ b/latest/Firmware/Transponder/Inc/bsp/bsp.hpp @@ -109,6 +109,8 @@ extern const char *BSP_HW_REV; #include #elif BOARD_REV == 100 #include +#elif BOARD_REV == 101 +#include #elif BOARD_REV == 105 #include #elif BOARD_REV == 109 diff --git a/latest/Firmware/Transponder/Inc/bsp/bsp_10_1.hpp b/latest/Firmware/Transponder/Inc/bsp/bsp_10_1.hpp new file mode 100644 index 0000000..03fb941 --- /dev/null +++ b/latest/Firmware/Transponder/Inc/bsp/bsp_10_1.hpp @@ -0,0 +1,98 @@ +/* + Copyright (c) 2016-2020 Peter Antypas + + This file is part of the MAIANA™ transponder firmware. + + The firmware 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 +*/ + +#ifndef INC_BSP_10_1_HPP_ +#define INC_BSP_10_1_HPP_ + + + +// GPIO Pin definitions +#define GNSS_EN_PORT GPIOC +#define GNSS_EN_PIN GPIO_PIN_14 + + +#define TRX_IC_CLK_PORT GPIOC +#define TRX_IC_CLK_PIN GPIO_PIN_15 + +#define CS2_PORT GPIOA +#define CS2_PIN GPIO_PIN_0 + +#define RX_EVT_PORT GPIOA +#define RX_EVT_PIN GPIO_PIN_1 + +#define GNSS_1PPS_PORT GPIOA +#define GNSS_1PPS_PIN GPIO_PIN_2 + +#define GNSS_NMEA_RX_PORT GPIOA +#define GNSS_NMEA_RX_PIN GPIO_PIN_3 + +#define CS1_PORT GPIOA +#define CS1_PIN GPIO_PIN_4 + +#define SCK_PORT GPIOA +#define SCK_PIN GPIO_PIN_5 + +#define MISO_PORT GPIOA +#define MISO_PIN GPIO_PIN_6 + +#define MOSI_PORT GPIOA +#define MOSI_PIN GPIO_PIN_7 + +#define SDN1_PORT GPIOB +#define SDN1_PIN GPIO_PIN_0 + +#define TRX_IC_DATA_PORT GPIOB +#define TRX_IC_DATA_PIN GPIO_PIN_1 + +#define PA_BIAS_PORT GPIOA +#define PA_BIAS_PIN GPIO_PIN_8 + +#define UART_TX_PORT GPIOA +#define UART_TX_PIN GPIO_PIN_9 + +#define UART_RX_PORT GPIOA +#define UART_RX_PIN GPIO_PIN_10 + +#define GNSS_STATE_PORT GPIOA +#define GNSS_STATE_PIN GPIO_PIN_11 + +#define TX_DISABLE_PORT GPIOA +#define TX_DISABLE_PIN GPIO_PIN_12 + +#define SDN2_PORT GPIOA +#define SDN2_PIN GPIO_PIN_15 + +#define RX_IC_CLK_PORT GPIOB +#define RX_IC_CLK_PIN GPIO_PIN_3 + +#define RX_IC_DATA_PORT GPIOB +#define RX_IC_DATA_PIN GPIO_PIN_4 + +#define TX_EVT_PORT GPIOB +#define TX_EVT_PIN GPIO_PIN_5 + +#define I2C_SCL_PORT GPIOB +#define I2C_SCL_PIN GPIO_PIN_6 + +#define I2C_SDA_PORT GPIOB +#define I2C_SDA_PIN GPIO_PIN_7 + + + +#endif /* INC_BSP_5_0_HPP_ */ diff --git a/latest/Firmware/Transponder/Src/Transceiver.cpp b/latest/Firmware/Transponder/Src/Transceiver.cpp index 572265a..8a9980a 100644 --- a/latest/Firmware/Transponder/Src/Transceiver.cpp +++ b/latest/Firmware/Transponder/Src/Transceiver.cpp @@ -157,7 +157,11 @@ void Transceiver::configureGPIOsForTX() gpiocfg.GPIO0 = 0x00; // No change gpiocfg.GPIO1 = 0x04; // RX/TX bit data gpiocfg.GPIO2 = 0x1F; // RX/TX bit clock - gpiocfg.GPIO3 = 0x20; // RX_STATE; high in TX, low in RX +#if BOARD_REV < 105 + gpiocfg.GPIO3 = 0x21; // RX_STATE; low during TX and high during RX +#else + gpiocfg.GPIO3 = 0x20; // RX_STATE; high during TX and low during RX +#endif gpiocfg.NIRQ = 0x00; // No change gpiocfg.SDO = 0x00; // No change gpiocfg.GENCFG = 0x00; // No change @@ -328,7 +332,11 @@ void Transceiver::configureGPIOsForRX() gpiocfg.GPIO0 = 0x00; // No change gpiocfg.GPIO1 = 0x14; // RX data bits gpiocfg.GPIO2 = 0x1F; // RX/TX data clock +#if BOARD_REV < 105 + gpiocfg.GPIO3 = 0x21; // RX_STATE; high during TX and low during RX +#else gpiocfg.GPIO3 = 0x20; // RX_STATE; high during TX and low during RX +#endif gpiocfg.NIRQ = 0x00; // No change gpiocfg.SDO = 0x00; // No change gpiocfg.GENCFG = 0x00; // No change diff --git a/latest/Firmware/Transponder/Src/bsp/bsp_10_1.cpp b/latest/Firmware/Transponder/Src/bsp/bsp_10_1.cpp new file mode 100644 index 0000000..e96f7ec --- /dev/null +++ b/latest/Firmware/Transponder/Src/bsp/bsp_10_1.cpp @@ -0,0 +1,752 @@ +/* + Copyright (c) 2016-2020 Peter Antypas + + This file is part of the MAIANA™ transponder firmware. + + The firmware 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 +*/ + + + +#include "bsp.hpp" +#include +#include "printf_serial.h" +#include + + + +#if BOARD_REV==101 + +#define EEPROM_ADDRESS (0x50 << 1) +#define EEPROM_STATION_ADDRESS 0x00 +#define EEPROM_CONFIG_ADDRESS 0x40 +#define STATION_DATA_FLASH_ADDRESS 0x0800F800 + +const char *BSP_HW_REV = "10.0.1"; + + + +I2C_HandleTypeDef hi2c1; +SPI_HandleTypeDef hspi1; +IWDG_HandleTypeDef hiwdg; +UART_HandleTypeDef huart2; +UART_HandleTypeDef huart1; +TIM_HandleTypeDef htim2; + +void SystemClock_Config(); + +char_input_cb gnssInputCallback = nullptr; +char_input_cb terminalInputCallback = nullptr; +irq_callback ppsCallback = nullptr; +irq_callback sotdmaCallback = nullptr; +irq_callback trxClockCallback = nullptr; +irq_callback rxClockCallback = nullptr; +irq_callback tickCallback = nullptr; + +// This should be plenty big (no need to be a whole flash page) +typedef union +{ + StationData station; + uint64_t dw[32]; +} StationDataPage; + +StationData __station = {0}; + +typedef struct +{ + GPIO_TypeDef *port; + GPIO_InitTypeDef gpio; + GPIO_PinState init; +} GPIO; + +static const GPIO __gpios[] = { + {GNSS_EN_PORT, {GNSS_EN_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_SET}, + {TRX_IC_CLK_PORT, {TRX_IC_CLK_PIN, GPIO_MODE_IT_RISING, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_RESET}, + {TX_DISABLE_PORT, {TX_DISABLE_PIN, GPIO_MODE_INPUT, GPIO_PULLUP, GPIO_SPEED_LOW, 0}, GPIO_PIN_SET}, + {CS2_PORT, {CS2_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_HIGH, 0}, GPIO_PIN_SET}, + {RX_EVT_PORT, {RX_EVT_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_RESET}, + {GNSS_1PPS_PORT, {GNSS_1PPS_PIN, GPIO_MODE_IT_RISING, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_RESET}, + {GNSS_NMEA_RX_PORT, {GNSS_NMEA_RX_PIN, GPIO_MODE_AF_PP, GPIO_PULLUP, GPIO_SPEED_LOW, GPIO_AF7_USART2}, GPIO_PIN_RESET}, + {CS1_PORT, {CS1_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_HIGH, 0}, GPIO_PIN_SET}, + {SCK_PORT, {SCK_PIN, GPIO_MODE_AF_PP, GPIO_NOPULL, GPIO_SPEED_HIGH, GPIO_AF5_SPI1}, GPIO_PIN_SET}, + {MISO_PORT, {MISO_PIN, GPIO_MODE_AF_PP, GPIO_NOPULL, GPIO_SPEED_HIGH, GPIO_AF5_SPI1}, GPIO_PIN_SET}, + {MOSI_PORT, {MOSI_PIN, GPIO_MODE_AF_PP, GPIO_NOPULL, GPIO_SPEED_HIGH, GPIO_AF5_SPI1}, GPIO_PIN_SET}, + {SDN1_PORT, {SDN1_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_SET}, + {TRX_IC_DATA_PORT, {TRX_IC_DATA_PIN, GPIO_MODE_INPUT, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_RESET}, + {TX_EVT_PORT, {TX_EVT_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_RESET}, + {UART_TX_PORT, {UART_TX_PIN, GPIO_MODE_AF_PP, GPIO_PULLUP, GPIO_SPEED_LOW, GPIO_AF7_USART1}, GPIO_PIN_RESET}, + {UART_RX_PORT, {UART_RX_PIN, GPIO_MODE_AF_PP, GPIO_PULLUP, GPIO_SPEED_LOW, GPIO_AF7_USART1}, GPIO_PIN_RESET}, + {GNSS_STATE_PORT, {GNSS_STATE_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_RESET}, + {SDN2_PORT, {SDN2_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_SET}, + {RX_IC_CLK_PORT, {RX_IC_CLK_PIN, GPIO_MODE_IT_RISING, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_RESET}, + {RX_IC_DATA_PORT, {RX_IC_DATA_PIN, GPIO_MODE_INPUT, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_RESET}, + {PA_BIAS_PORT, {PA_BIAS_PIN, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL, GPIO_SPEED_LOW, 0}, GPIO_PIN_RESET}, + {I2C_SCL_PORT, {I2C_SCL_PIN, GPIO_MODE_AF_OD, GPIO_PULLUP, GPIO_SPEED_HIGH, GPIO_AF4_I2C1}, GPIO_PIN_SET}, + {I2C_SDA_PORT, {I2C_SDA_PIN, GPIO_MODE_AF_OD, GPIO_PULLUP, GPIO_SPEED_HIGH, GPIO_AF4_I2C1}, GPIO_PIN_SET}, +}; + +extern "C" +{ + void Error_Handler(uint8_t i) + { + asm("BKPT 0"); + printf_serial_now("[ERROR %d]\r\n", i); + //printf_serial_now("[ERROR] ***** System error handler resetting *****\r\n"); + //NVIC_SystemReset(); + } +} + + +void gpio_pin_init(); + +void bsp_hw_init() +{ + HAL_Init(); + SystemClock_Config(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + + __HAL_RCC_USART2_CLK_ENABLE(); + __HAL_RCC_USART1_CLK_ENABLE(); + __HAL_RCC_SPI1_CLK_ENABLE(); + __HAL_RCC_TIM2_CLK_ENABLE(); + __HAL_RCC_I2C1_CLK_ENABLE(); + + gpio_pin_init(); + + + + // USART1 (main UART) + huart1.Instance = USART1; + huart1.Init.BaudRate = 38400; + huart1.Init.WordLength = UART_WORDLENGTH_8B; + huart1.Init.StopBits = UART_STOPBITS_1; + huart1.Init.Parity = UART_PARITY_NONE; + huart1.Init.Mode = UART_MODE_TX_RX; + huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart1.Init.OverSampling = UART_OVERSAMPLING_16; + huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; + huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; + HAL_UART_Init(&huart1); + + HAL_NVIC_SetPriority(USART1_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(USART1_IRQn); + __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); + + + // SPI + + hspi1.Instance = SPI1; + hspi1.Init.Mode = SPI_MODE_MASTER; + hspi1.Init.Direction = SPI_DIRECTION_2LINES; + hspi1.Init.DataSize = SPI_DATASIZE_8BIT; + hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; + hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; + hspi1.Init.NSS = SPI_NSS_SOFT; + hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; + hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; + hspi1.Init.TIMode = SPI_TIMODE_DISABLE; + hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + hspi1.Init.CRCPolynomial = 7; + hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; + hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; + + if (HAL_SPI_Init(&hspi1) != HAL_OK) + { + Error_Handler(0); + } + + __HAL_SPI_ENABLE(&hspi1); + + + // I2C + hi2c1.Instance = I2C1; + hi2c1.Init.Timing = 0x00702991; + hi2c1.Init.OwnAddress1 = 0; + hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c1.Init.OwnAddress2 = 0; + hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK; + hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + if (HAL_I2C_Init(&hi2c1) != HAL_OK) + { + Error_Handler(0); + } + /** Configure Analogue filter + */ + if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK) + { + Error_Handler(0); + } + /** Configure Digital filter + */ + if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK) + { + Error_Handler(0); + } + + // USART2 (GNSS, RX only) + huart2.Instance = USART2; + huart2.Init.BaudRate = 9600; + huart2.Init.WordLength = UART_WORDLENGTH_8B; + huart2.Init.StopBits = UART_STOPBITS_1; + huart2.Init.Parity = UART_PARITY_NONE; + huart2.Init.Mode = UART_MODE_TX_RX; + huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart2.Init.OverSampling = UART_OVERSAMPLING_16; + huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; + huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; + HAL_UART_Init(&huart2); + + HAL_NVIC_SetPriority(USART2_IRQn, 7, 0); + HAL_NVIC_EnableIRQ(USART2_IRQn); + __HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE); + + // TIM2 for SOTDMA (37.5Hz) + uint32_t period = (SystemCoreClock / 37.5) - 1; + + __HAL_RCC_TIM2_CLK_ENABLE(); + htim2.Instance = TIM2; + htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim2.Init.Prescaler = 0; + htim2.Init.CounterMode = TIM_COUNTERMODE_UP; + htim2.Init.Period = period; + htim2.Init.RepetitionCounter = 0; + + HAL_TIM_Base_Init(&htim2); + + // 1PPS signal + HAL_NVIC_SetPriority(EXTI2_IRQn, 6, 0); + HAL_NVIC_EnableIRQ(EXTI2_IRQn); + + // SOTDMA + HAL_NVIC_SetPriority(TIM2_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(TIM2_IRQn); + + // RF IC clock interrupts + HAL_NVIC_SetPriority(EXTI15_10_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); + + HAL_NVIC_SetPriority(EXTI3_IRQn, 1, 0); + HAL_NVIC_EnableIRQ(EXTI3_IRQn); + + bsp_read_station_data(&__station); +} + + + +void SystemClock_Config() +{ + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_PeriphCLKInitTypeDef PeriphClkInit; + + /**Initializes the CPU, AHB and APB bus clocks + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; + RCC_OscInitStruct.PLL.PLLM = 1; + RCC_OscInitStruct.PLL.PLLN = 10; // 80 MHz +#if defined(STM32L432xx) || defined(STM32L431xx) + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7; +#endif + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + Error_Handler(0); + } + + /**Initializes the CPU, AHB and APB bus clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) + { + Error_Handler(0); + } + + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1; + PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_HSI; + PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) + { + Error_Handler(0); + } + + /**Configure the main internal regulator output voltage + */ + if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) + { + Error_Handler(0); + } + + /**Configure the Systick interrupt time + */ + HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); + + /**Configure the Systick + */ + HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); + + /* SysTick_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); + +} + +void gpio_pin_init() +{ + for ( unsigned i = 0; i < sizeof __gpios / sizeof(GPIO); ++i ) + { + const GPIO* io = &__gpios[i]; + if ( io->gpio.Mode == GPIO_MODE_OUTPUT_PP || io->gpio.Mode == GPIO_MODE_OUTPUT_OD ) + { + HAL_GPIO_WritePin(io->port, io->gpio.Pin, io->init); + } + HAL_GPIO_Init(io->port, (GPIO_InitTypeDef*)&io->gpio); + } +} + +void HAL_MspInit(void) +{ + /* USER CODE BEGIN MspInit 0 */ + + /* USER CODE END MspInit 0 */ + + __HAL_RCC_SYSCFG_CLK_ENABLE(); + __HAL_RCC_PWR_CLK_ENABLE(); + + HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); + + /** + * Some of these interrupts will be managed and configured in FreeRTOS + */ + + /* System interrupt init*/ + /* MemoryManagement_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(MemoryManagement_IRQn, 0, 0); + /* BusFault_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(BusFault_IRQn, 0, 0); + /* UsageFault_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(UsageFault_IRQn, 0, 0); + /* SVCall_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(SVCall_IRQn, 10, 0); + /* DebugMonitor_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(DebugMonitor_IRQn, 0, 0); + /* PendSV_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(PendSV_IRQn, 10, 0); + /* SysTick_IRQn interrupt configuration */ + HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); + + /* USER CODE BEGIN MspInit 1 */ + + /* USER CODE END MspInit 1 */ +} + +bool bsp_is_tx_hardwired() +{ + // Always true for this board. It will get more involved later. Or maybe never ... + return true; +} + +void bsp_erase_flash_station_data() +{ + uint32_t page = (STATION_DATA_FLASH_ADDRESS - FLASH_BASE) / FLASH_PAGE_SIZE; + + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); + if ( HAL_FLASH_Unlock() != HAL_OK ) + return; + + FLASH_EraseInitTypeDef erase; + erase.TypeErase = FLASH_TYPEERASE_PAGES; + erase.Banks = FLASH_BANK_1; + erase.Page = page; + erase.NbPages = 1; + + uint32_t errPage; + HAL_FLASHEx_Erase(&erase, &errPage); + HAL_FLASH_Lock(); +} + + +void bsp_read_station_data(StationData *data) +{ + /** + * If there is legacy data in MCU flash, migrate it automatically to EEPROM!!! + */ + + StationData *__d = (StationData*)STATION_DATA_FLASH_ADDRESS; + if ( __d->magic == STATION_DATA_MAGIC ) + { + bsp_write_station_data(*__d); + bsp_erase_flash_station_data(); + } + + uint8_t *d = (uint8_t*)data; + for ( uint8_t i = 0; i < sizeof (StationData); ++i, ++d ) + { + HAL_I2C_Mem_Read(&hi2c1, EEPROM_ADDRESS|1, i+EEPROM_STATION_ADDRESS, 1, d, 1, 5); + } +} + +void bsp_write_station_data(const StationData &data) +{ + __station = data; + uint8_t *d = (uint8_t*)&__station; + for ( uint8_t i = 0; i < sizeof (StationData); ++i, ++d ) + { + HAL_I2C_Mem_Write(&hi2c1, EEPROM_ADDRESS, i+EEPROM_STATION_ADDRESS, 1, d, 1, 5); + HAL_Delay(5); + } +} + +void bsp_erase_station_data() +{ + bsp_write_station_data({0}); +} + +bool bsp_is_station_data_provisioned() +{ + return __station.magic == STATION_DATA_MAGIC; +} + +void bsp_read_config_flags(ConfigFlags *flags) +{ + uint8_t *d = (uint8_t*)flags; + for ( uint8_t i = 0; i < sizeof (ConfigFlags); ++i, ++d ) + { + HAL_I2C_Mem_Read(&hi2c1, EEPROM_ADDRESS|1, i+EEPROM_CONFIG_ADDRESS, 1, d, 1, 5); + } +} + +void bsp_write_config_flags(const ConfigFlags &flags) +{ + ConfigFlags __f = flags; + uint8_t *d = (uint8_t*)&__f; + for ( uint8_t i = 0; i < sizeof (ConfigFlags); ++i, ++d ) + { + HAL_I2C_Mem_Write(&hi2c1, EEPROM_ADDRESS, i+EEPROM_CONFIG_ADDRESS, 1, d, 1, 5); + HAL_Delay(5); + } +} + + +void bsp_erase_config_flags() +{ + bsp_write_config_flags({0}); +} + +void bsp_set_rx_mode() +{ + HAL_GPIO_WritePin(PA_BIAS_PORT, PA_BIAS_PIN, GPIO_PIN_RESET); // Kill the RF MOSFET bias voltage + GPIO_InitTypeDef gpio; + gpio.Pin = TRX_IC_DATA_PIN; + gpio.Mode = GPIO_MODE_INPUT; + gpio.Speed = GPIO_SPEED_FREQ_LOW; + gpio.Pull = GPIO_NOPULL; + HAL_GPIO_Init(TRX_IC_DATA_PORT, &gpio); +} + +void bsp_rx_led_on() +{ + HAL_GPIO_WritePin(RX_EVT_PORT, RX_EVT_PIN, GPIO_PIN_SET); +} + +void bsp_rx_led_off() +{ + HAL_GPIO_WritePin(RX_EVT_PORT, RX_EVT_PIN, GPIO_PIN_RESET); +} + +void bsp_tx_led_on() +{ +#if LEGACY_BREAKOUTS + HAL_GPIO_WritePin(TX_EVT_PORT, TX_EVT_PIN, GPIO_PIN_RESET); +#else + HAL_GPIO_WritePin(TX_EVT_PORT, TX_EVT_PIN, GPIO_PIN_SET); +#endif +} + +void bsp_tx_led_off() +{ +#if LEGACY_BREAKOUTS + HAL_GPIO_WritePin(TX_EVT_PORT, TX_EVT_PIN, GPIO_PIN_SET); +#else + HAL_GPIO_WritePin(TX_EVT_PORT, TX_EVT_PIN, GPIO_PIN_RESET); +#endif +} + +void bsp_gps_led_on() +{ + HAL_GPIO_WritePin(GNSS_STATE_PORT, GNSS_STATE_PIN, GPIO_PIN_SET); +} + +void bsp_gps_led_off() +{ + HAL_GPIO_WritePin(GNSS_STATE_PORT, GNSS_STATE_PIN, GPIO_PIN_RESET); +} + +void bsp_set_tx_mode() +{ + GPIO_InitTypeDef gpio; + gpio.Pin = TRX_IC_DATA_PIN; + gpio.Mode = GPIO_MODE_OUTPUT_PP; + gpio.Speed = GPIO_SPEED_FREQ_LOW; + gpio.Pull = GPIO_NOPULL; + HAL_GPIO_Init(TRX_IC_DATA_PORT, &gpio); + + HAL_GPIO_WritePin(PA_BIAS_PORT, PA_BIAS_PIN, GPIO_PIN_SET); // RF MOSFET bias voltage +} + +void bsp_gnss_on() +{ + HAL_GPIO_WritePin(GNSS_EN_PORT, GNSS_EN_PIN, GPIO_PIN_SET); +} + +void bsp_gnss_off() +{ + HAL_GPIO_WritePin(GNSS_EN_PORT, GNSS_EN_PIN, GPIO_PIN_RESET); +} + +bool bsp_is_gnss_on() +{ + return HAL_GPIO_ReadPin(GNSS_EN_PORT, GNSS_EN_PIN) == GPIO_PIN_RESET; +} + +void USART_putc(USART_TypeDef* USARTx, char c) +{ + while ( !(USARTx->ISR & USART_ISR_TXE) ) + ; + + USARTx->TDR = c; +} + +void bsp_write_char(char c) +{ + USART_putc(USART1, c); +} + +void bsp_write_string(const char *s) +{ + for ( int i = 0; s[i] != 0; ++i ) + USART_putc(USART1, s[i]); +} + +void bsp_start_wdt() +{ + IWDG_InitTypeDef iwdg; + iwdg.Prescaler = IWDG_PRESCALER_16; + iwdg.Reload = 0x0fff; + iwdg.Window = 0x0fff; + + hiwdg.Instance = IWDG; + hiwdg.Init = iwdg; + + HAL_IWDG_Init(&hiwdg); +} + +void bsp_refresh_wdt() +{ + HAL_IWDG_Refresh(&hiwdg); +} + +void bsp_set_gnss_input_callback(char_input_cb cb) +{ + gnssInputCallback = cb; +} + +void bsp_set_terminal_input_callback(char_input_cb cb) +{ + terminalInputCallback = cb; +} + +void bsp_set_tick_callback(irq_callback cb) +{ + tickCallback = cb; +} + +void bsp_start_sotdma_timer() +{ + HAL_TIM_Base_Start_IT(&htim2); +} + +void bsp_stop_sotdma_timer() +{ + HAL_TIM_Base_Stop_IT(&htim2); +} + +void bsp_set_gnss_1pps_callback(irq_callback cb) +{ + ppsCallback = cb; +} + +void bsp_set_trx_clk_callback(irq_callback cb) +{ + trxClockCallback = cb; +} + +void bsp_set_rx_clk_callback(irq_callback cb) +{ + rxClockCallback = cb; +} + +void bsp_set_gnss_sotdma_timer_callback(irq_callback cb) +{ + sotdmaCallback = cb; +} + +uint32_t bsp_get_sotdma_timer_value() +{ + return TIM2->CNT; +} + +void bsp_set_sotdma_timer_value(uint32_t v) +{ + TIM2->CNT = v; +} + +uint32_t bsp_get_system_clock() +{ + return SystemCoreClock; +} + +uint8_t bsp_tx_spi_byte(uint8_t data) +{ + uint8_t result = 0; + HAL_SPI_TransmitReceive(&hspi1, &data, &result, 1, 2); + return result; +} + +void bsp_reboot() +{ + NVIC_SystemReset(); +} + +bool bsp_is_tx_disabled() +{ + return HAL_GPIO_ReadPin(TX_DISABLE_PORT, TX_DISABLE_PIN) == GPIO_PIN_RESET; +} + +void bsp_enter_dfu() +{ + // Cut off the GPS signals immediately to prevent its UART from transmitting and hijacking the bootloader upon reset + bsp_gnss_off(); + + HAL_Delay(1000); + + // This flag simply tells main() to jump to the ROM bootloader immediately upon reset, before initializing anything + *(uint32_t*)BOOTMODE_ADDRESS = DFU_FLAG_MAGIC; + + bsp_reboot(); +} + +void bsp_signal_rx_event() +{ + HAL_GPIO_WritePin(RX_EVT_PORT, RX_EVT_PIN, GPIO_PIN_SET); +} + + +void bsp_signal_gps_status(bool tracking) +{ + HAL_GPIO_WritePin(GNSS_STATE_PORT, GNSS_STATE_PIN, tracking ? GPIO_PIN_SET: GPIO_PIN_RESET); +} + +extern "C" +{ + + void USART1_IRQHandler(void) + { + if ( __HAL_UART_GET_IT(&huart1, UART_IT_RXNE) ) + { + __HAL_UART_CLEAR_IT(&huart1, UART_IT_RXNE); + char c = USART1->RDR; + if ( terminalInputCallback ) + terminalInputCallback(c); + } + } + + void EXTI2_IRQHandler(void) + { + if ( __HAL_GPIO_EXTI_GET_IT(GNSS_1PPS_PIN) != RESET ) + { + __HAL_GPIO_EXTI_CLEAR_IT(GNSS_1PPS_PIN); + if ( ppsCallback ) + ppsCallback(); + } + } + + void USART2_IRQHandler() + { + if ( __HAL_UART_GET_IT(&huart2, UART_IT_RXNE) ) + { + __HAL_UART_CLEAR_IT(&huart2, UART_IT_RXNE); + char c = (char)USART2->RDR; + if ( gnssInputCallback ) + gnssInputCallback(c); + } + } + + + void TIM2_IRQHandler(void) + { + if(__HAL_TIM_GET_FLAG(&htim2, TIM_FLAG_UPDATE) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(&htim2, TIM_IT_UPDATE) !=RESET) + { + __HAL_TIM_CLEAR_IT(&htim2, TIM_IT_UPDATE); + if ( sotdmaCallback ) + sotdmaCallback(); + } + } + } + + void EXTI3_IRQHandler(void) + { + if ( __HAL_GPIO_EXTI_GET_IT(RX_IC_CLK_PIN) != RESET ) + { + __HAL_GPIO_EXTI_CLEAR_IT(RX_IC_CLK_PIN); + if ( rxClockCallback ) + rxClockCallback(); + } + } + + void EXTI15_10_IRQHandler(void) + { + if ( __HAL_GPIO_EXTI_GET_IT(TRX_IC_CLK_PIN) != RESET ) + { + __HAL_GPIO_EXTI_CLEAR_IT(TRX_IC_CLK_PIN); + if ( trxClockCallback ) + trxClockCallback(); + } + } + + void HAL_SYSTICK_Callback() + { + if ( tickCallback ) + tickCallback(); + } + +} + +#endif