Changeset - 02d3447dac18
[Not reviewed]
default
0 4 0
Ethan Zonca (ethanzonca) - 9 years ago 2017-01-12 09:21:40
e@ethanzonca.com
Add docs, remove startup delays
4 files changed with 73 insertions and 18 deletions:
0 comments (0 inline, 0 general)
Libraries/Si446x/si446x.c
Show inline comments
 
//
 
// Si446x: Initializes and configures a Si446x transceiver over SPI
 
//
 
/*
 
 * FeatherHAB
 
 *
 
 * This file is part of FeatherHAB.
 
 *
 
 * FeatherHab is free software: you can redistribute it and/or modify
 
 * it under the terms of the GNU Affero General Public License as published by
 
 * the Free Software Foundation, either version 3 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * FeatherHab 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 Affero General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU Affero General Public License
 
 * along with FeatherHAB. If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 * Ethan Zonca
 
 *
 
 */
 
 
#include "stm32f0xx_hal.h"
 
 
#include "si446x.h"
 
#include "config.h"
 
#include "error.h"
 
#include "system/gpio.h"
 
#include "system/sysclk.h"
 
 
 
// Private variables
 
static SPI_HandleTypeDef hspi1;
 
static uint8_t si446x_cw_status = 0;
 
 
 
// Private function prototypes
 
static void __init_spi1(void);
 
 
 
// Initialize Si446x in 2FSK transmit mode
 
void si446x_init(void)
 
{
 
	// init spi port
 
	__init_spi1();
 
 
	GPIO_InitTypeDef GPIO_InitStruct;
 
 
	// GPIO: TCXO control
 
	GPIO_InitStruct.Pin = SI446x_TCXO_EN_PIN;
 
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 
	GPIO_InitStruct.Pull = GPIO_NOPULL;
 
	HAL_GPIO_Init(SI446x_TCXO_EN_PORT, &GPIO_InitStruct);
 
	HAL_GPIO_WritePin(SI446x_TCXO_EN_PORT, SI446x_TCXO_EN_PIN, 1);
 
 
	// GPIO: VHF radio shutdown control
 
	GPIO_InitStruct.Pin = SI446x_SHUTDOWN_PIN;
 
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 
	GPIO_InitStruct.Pull = GPIO_NOPULL;
 
	HAL_GPIO_Init(SI446x_SHUTDOWN_PORT, &GPIO_InitStruct);
 
 
	// Perform PoR (takes 20ms) and turn device on
 
	si446x_reset();
 
	si446x_reset();
 
 
    // Divide SI446x_VCXO_FREQ into its bytes; MSB first
 
    uint16_t x3 = SI446x_VCXO_FREQ / 0x1000000;
 
    uint16_t x2 = (SI446x_VCXO_FREQ - x3 * 0x1000000) / 0x10000;
 
    uint16_t x1 = (SI446x_VCXO_FREQ - x3 * 0x1000000 - x2 * 0x10000) / 0x100;
 
    uint16_t x0 = (SI446x_VCXO_FREQ - x3 * 0x1000000 - x2 * 0x10000 - x1 * 0x100);
 
 
    // Power up radio module                          boot  xtal  _XO_frequency_
 
 
    //TCXO
 
    const char init_command[] = {SI446x_CMD_POWER_UP, 0x01, 0x01, x3, x2, x1, x0};
 
    si446x_sendcmd(7, init_command, SI446x_CHECK_ACK);
 
 
    HAL_Delay(10);
 
 
	// Change to SPI Ready state EMZ added for re-init, might help on startup
 
	uint8_t change_state_commanda[] = {SI446x_CMD_CHANGE_STATE, 0x02}; //  Change to spi ready
 
    si446x_sendcmd(2, change_state_commanda, SI446x_CHECK_ACK);
 
    HAL_Delay(10);
 
 
    // Radio ready: clear all pending interrupts and get the interrupt status back
 
	uint8_t get_int_status_command[] = {SI446x_CMD_GET_INT_STATUS, 0x00, 0x00, 0x00};
 
    si446x_sendcmd(4, get_int_status_command, SI446x_CHECK_ACK);
 
 
    HAL_Delay(10);
 
 
    // GPIO config: Set all GPIOs LOW; Link NIRQ to CTS; Link SDO to MISO; Max drive strength
 
	uint8_t gpio_pin_cfg_command[] = {
 
    		SI446x_CMD_GPIO_PIN_CFG, // Command
 
			SI446x_GPIO_LOW,      // GPIO0 - Power amp control DAC AD5611 Sync Pin
 
			SI446x_GPIO_INPUT,    // GPIO1 - Input for modulation
 
			SI446x_GPIO_LOW,      // GPIO2 - Blue LED
 
			SI446x_GPIO_NOCHANGE, // GPIO3 - Unused
 
			SI446x_GPIO_NOCHANGE, // NIRQ
 
			SI446x_GPIO_NOCHANGE, // 0x11, // SDO
 
			SI446x_GPIO_NOCHANGE, // Gencfg
 
	};
 
    si446x_sendcmd(8, gpio_pin_cfg_command, SI446x_CHECK_ACK);
 
 
    HAL_Delay(10);
 
 
//	uint8_t tune_xo_cmd[] = {
 
//    		SI446x_CMD_SET_PROPERTY,
 
//			SI446x_XO_TUNE_REGISTER_GROUP,
 
//			0x1, // num data
 
//			SI446x_XO_TUNE_REGISTER_PROP,
 
//			SI446x_CRYSTAL_LOAD_TUNING,
 
//    };
 
//    si446x_sendcmd(5, tune_xo_cmd, SI446x_CHECK_ACK);
 
 
    HAL_Delay(10);
 
 
    // Tune to frequency specified
 
	si446x_setchannel(TUNE_FREQUENCY);
 
 
	HAL_Delay(10);
 
 
    // Set to 2FSK mode
 
    uint8_t modemconfig = SI446x_MOD_TYPE_2FSK | SI446x_MOD_TYPE_SOURCE_DIRECTMODE | SI446x_MOD_TYPE_DIRECT_ASYNCH | SI446x_MOD_TYPE_DIRECT_SOURCE_GPIO1; //SI446x_MOD_TYPE_SOURCE_PACKETHANDLER
 
    uint8_t set_modem_mod_type_command[] = {
 
    		SI446x_CMD_SET_PROPERTY,
 
    		SI446x_MOD_TYPE_REGISTER_GROUP,
 
			0x01, // num data
 
			SI446x_MOD_TYPE_REGISTER_PROP,
 
			modemconfig
 
    };
 
    si446x_sendcmd(5, set_modem_mod_type_command, SI446x_CHECK_ACK);
 
 
    HAL_Delay(10);
 
 
	// Set Si446x initial output power, input to power amp (0-0x7F, 0mW - 40mw?)
 
	uint8_t basepower = 0x02;
 
	// FIXME: basepower should be 0x10 for underperforming units and 0x04 for normal units
 
    uint8_t set_power_level_command[] = {SI446x_CMD_SET_PROPERTY, 0x22, 0x01, 0x01, basepower};
 
	si446x_sendcmd(5, set_power_level_command, SI446x_CHECK_ACK);
 
 
 
	HAL_Delay(10);
 
 
    // Set air data rate
 
    si446x_setdatarate();
 
    HAL_Delay(10);
 
 
	// Tune TX
 
	uint8_t change_state_command[] = {SI446x_CMD_CHANGE_STATE, 0x05}; //  Change to TX tune state
 
    si446x_sendcmd(2, change_state_command, SI446x_CHECK_ACK);
 
    HAL_Delay(10);
 
 
	si446x_cw_status = 0;
 
}
 
 
 
// Perform power-on-reset of Si446x. Takes 20ms.
 
void si446x_reset(void)
 
{
 
	si446x_shutdown();
 
	HAL_Delay(10);
 
	si446x_wakeup();
 
	HAL_Delay(10);
 
}
 
 
 
// Set GPIO pin state on Si446x
 
void si446x_gpio(uint8_t gpio, uint8_t state, uint8_t doack)
 
{
 
	// GPIO invalid
 
	if(gpio > 7)
 
		return;
 
 
	// Default to not changing any GPIO
 
	uint8_t gpio_pin_cfg_command[] = {
 
			SI446x_CMD_GPIO_PIN_CFG, // Command
 
			SI446x_GPIO_NOCHANGE, // GPIO0 - Power amp control DAC AD5611 Sync Pin
 
			SI446x_GPIO_NOCHANGE, // GPIO1 - Input for modulation
 
			SI446x_GPIO_NOCHANGE, // GPIO2 - Blue
 
			SI446x_GPIO_NOCHANGE, // GPIO3 - Unused
 
			SI446x_GPIO_NOCHANGE, // NIRQ
 
			SI446x_GPIO_NOCHANGE, // 0x11, // SDO
 
			SI446x_GPIO_NOCHANGE, // Gencfg
 
	};
 
 
	// Set requested GPIO to requested state
 
	gpio_pin_cfg_command[gpio+1] = state;
 
 
	si446x_sendcmd(8, gpio_pin_cfg_command, doack);
 
}
 
 
 
// Set over-air data rate
 
void si446x_setdatarate(void)
 
{
 
    // Set data rate (unsure if this actually affects direct modulation)
 
                         //        set prop   group     numprops  startprop   data
 
	uint8_t set_data_rate_command[] = {SI446x_CMD_SET_PROPERTY,     0x20,     0x03,     0x03,       0x0F, 0x42, 0x40};
 
    si446x_sendcmd(7, set_data_rate_command, SI446x_CHECK_ACK);
 
}
 
 
 
// Block write data to the Si446x SPI interface, up to 128 byte length
 
void si446x_senddata(uint8_t* data, uint8_t len)
 
{
 
	uint8_t dummy[128];
 
	SI446x_SELECT;
 
	HAL_SPI_TransmitReceive(&hspi1, data, dummy, len, SI446x_TIMEOUT);
 
	SI446x_DESELECT;
 
}
 
 
 
// Delay approximately 20us
Source/main.c
Show inline comments
 
//
 
// mBuoy Depth Select Firmware
 
// Copyright 2015 SeaLandAire Technologies
 
//
 
/*
 
 * FeatherHAB
 
 *
 
 * This file is part of FeatherHAB.
 
 *
 
 * FeatherHab is free software: you can redistribute it and/or modify
 
 * it under the terms of the GNU Affero General Public License as published by
 
 * the Free Software Foundation, either version 3 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * FeatherHab 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 Affero General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU Affero General Public License
 
 * along with FeatherHAB. If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 * Ethan Zonca
 
 *
 
 */
 
 
#include "stm32f0xx_hal.h"
 
 
#include "config.h"
 
#include "error.h"
 
#include "pressure.h"
 
#include "gps.h"
 
 
#include "system/gpio.h"
 
#include "system/sysclk.h"
 
#include "system/watchdog.h"
 
#include "system/uart.h"
 
#include "system/adc.h"
 
#include "stm32f0xx_hal.h"
 
 
#include "si446x/si446x.h"
 
#include "aprs/aprs.h"
 
#include "aprs/afsk.h"
 
#include "pressure.h"
 
#include "gps.h"
 
 
 
int main(void)
 
{
 
  hal_init();
 
  sysclock_init();
 
  gpio_init();
 
 
  HAL_Delay(100);
 
 
  adc_init();
 
 
  afsk_init();
 
  si446x_init();
 
  si446x_init();
 
 
  HAL_Delay(100);
 
 
  gps_poweron();
 
  HAL_Delay(100);
 
 
  pressure_init();
 
 
  // Software timers
 
  uint32_t last_transmission = HAL_GetTick();
 
  uint32_t last_led = HAL_GetTick();
 
 
  while (1)
 
  {
 
	  // Blink LEDs
 
	  if(HAL_GetTick() - last_transmission > 700)
 
	  {
 
		  gps_update_data(); // Will always return at 1hz rate (default measurement rate)
 
		  pressure_read();
 
		  aprs_send();
 
		  //while(afsk_busy());
 
 
		  last_transmission = HAL_GetTick();
 
	  }
 
 
	  if(HAL_GetTick() - last_led > 100)
 
	  {
 
		  HAL_GPIO_TogglePin(LED_POWER);
 
		  last_led = HAL_GetTick();
 
	  }
 
 
	  if(afsk_request_cwoff())
 
		  si446x_cw_off();
 
 
	  // High-frequency function calls
 
//	  watchdog_feed();
 
  }
 
}
 
Source/system/gpio.c
Show inline comments
 
//
 
// GPIO: Configure and initialize GPIOs
 
//
 
/*
 
 * FeatherHAB
 
 *
 
 * This file is part of FeatherHAB.
 
 *
 
 * FeatherHab is free software: you can redistribute it and/or modify
 
 * it under the terms of the GNU Affero General Public License as published by
 
 * the Free Software Foundation, either version 3 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * FeatherHab 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 Affero General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU Affero General Public License
 
 * along with FeatherHAB. If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 * Ethan Zonca
 
 *
 
 */
 
 
#include "config.h"
 
#include "system/gpio.h"
 
#include "stm32f0xx_hal.h"
 
 
 
// Private variables
 
static uint8_t shutdown_triggered = 0;
 
static uint32_t shutdown_triggered_time = 0;
 
 
 
// Initialize GPIOs
 
void gpio_init(void)
 
{
 
  GPIO_InitTypeDef GPIO_InitStruct;
 
 
  // Enable clocks
 
  __GPIOC_CLK_ENABLE();
 
  __GPIOF_CLK_ENABLE();
 
  __GPIOA_CLK_ENABLE();
 
  __GPIOB_CLK_ENABLE();
 
 
  // LEDs 1/2
 
  GPIO_InitStruct.Pin = PIN_LED_POWER;
 
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 
  GPIO_InitStruct.Pull = GPIO_NOPULL;
 
  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
 
  HAL_GPIO_Init(PORT_LED_POWER, &GPIO_InitStruct);
 
 
  GPIO_InitStruct.Pin = GPS_NOTEN_PIN;
 
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 
  GPIO_InitStruct.Pull = GPIO_NOPULL;
 
  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
 
  HAL_GPIO_Init(GPS_NOTEN_PORT, &GPIO_InitStruct);
 
  HAL_GPIO_WritePin(GPS_NOTEN, 1); // yes, keep the chip disabled
 
 
 
  // Toggle the power LED
 
  HAL_GPIO_TogglePin(LED_POWER);
 
}
Source/system/uart.c
Show inline comments
 
//
 
// uart: configure and initialize GPS uart
 
//
 
 
#include "stm32f0xx_hal.h"
 
 
#include "system/uart.h"
 
#include "config.h"
 
#include "system/gpio.h"
 
 
UART_HandleTypeDef huart1;
 
DMA_HandleTypeDef hdma_usart1_rx;
 
DMA_HandleTypeDef hdma_usart1_tx;
 
uint8_t uart_initted = 0;
 
 
void uart_init(void)
 
{
 
    __GPIOB_CLK_ENABLE();
 
    __USART1_CLK_ENABLE();
 
 
    GPIO_InitTypeDef GPIO_InitStruct;
 
 
    // Init gpio pins for uart
 
    GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
 
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 
    GPIO_InitStruct.Pull = GPIO_NOPULL; //GPIO_PULLUP;
 
    GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
 
    GPIO_InitStruct.Alternate = GPIO_AF1_USART1;
 
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
 
    // Init UART periph
 
    huart1.Instance = USART1;
 
    huart1.Init.BaudRate = 9600;
 
    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_RXOVERRUNDISABLE_INIT|UART_ADVFEATURE_DMADISABLEONERROR_INIT;
 
    huart1.AdvancedInit.OverrunDisable = UART_ADVFEATURE_OVERRUN_DISABLE;
 
    huart1.AdvancedInit.DMADisableonRxError = UART_ADVFEATURE_DMA_DISABLEONRXERROR;
 
    HAL_UART_Init(&huart1);
 
 
    HAL_Delay(100);
 
	uint8_t switch_baud[] = "$PUBX,41,1,0003,0001,115200,0*1E\r\n";
 
	HAL_UART_Transmit(uart_gethandle(), switch_baud, sizeof(switch_baud)/sizeof(uint8_t), 1000);
 
 
    HAL_UART_DeInit(&huart1);
 
    huart1.Init.BaudRate = 115200;
 
    HAL_UART_Init(&huart1);
 
 
 
//
 
//    __DMA1_CLK_ENABLE();
 
//
 
//  // Init UART DMA
 
//    hdma_usart1_rx.Instance = DMA1_Channel3;
 
//    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
 
//    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
 
//    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
 
//    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
 
//    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
 
//    hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
 
//    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
 
//    HAL_DMA_Init(&hdma_usart1_rx);
 
//
 
//    __HAL_LINKDMA(&huart1,hdmarx,hdma_usart1_rx);
 
//
 
//    hdma_usart1_tx.Instance = DMA1_Channel2;
 
//    hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
 
//    hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
 
//    hdma_usart1_tx.Init.MemInc = DMA_MINC_DISABLE;
 
//    hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
 
//    hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
 
//    hdma_usart1_tx.Init.Mode = DMA_NORMAL;
 
//    hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
 
//    HAL_DMA_Init(&hdma_usart1_tx);
 
//
 
//    __HAL_LINKDMA(&huart1,hdmatx,hdma_usart1_tx);
 
//
 
////    HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0);
 
////    HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
 
 
    HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
 
    //HAL_NVIC_EnableIRQ(USART1_IRQn);
 
    HAL_NVIC_DisableIRQ(USART1_IRQn);
 
 
    uart_initted = 1;
 
}
 
 
void uart_deinit(void)
 
{
 
    if(uart_initted == 1)
 
    {
 
        //HAL_DMA_DeInit(&hdma_usart1_rx);
 
        //HAL_DMA_DeInit(&hdma_usart1_tx);
 
        HAL_UART_DeInit(&huart1);
 
        __HAL_RCC_USART1_CLK_DISABLE();
 
 
        uart_initted = 0;
 
    }
 
}
 
 
UART_HandleTypeDef* uart_gethandle(void)
 
{
 
    return &huart1;
 
} 
 
 
DMA_HandleTypeDef* uart_get_txdma_handle(void)
 
{
 
    return &hdma_usart1_tx;
 
}
 
DMA_HandleTypeDef* uart_get_rxdma_handle(void)
 
{
 
    return &hdma_usart1_rx;
 
}
 
0 comments (0 inline, 0 general)