Changeset - 851511077b87
[Not reviewed]
default
0 4 0
Ethan Zonca (ethanzonca) - 9 years ago 2017-01-03 15:13:32
e@ethanzonca.com
Fix issue where miso was never initted
4 files changed with 7 insertions and 10 deletions:
0 comments (0 inline, 0 general)
Libraries/Si446x/si446x.c
Show inline comments
 
@@ -128,298 +128,299 @@ void si446x_init(void)
 
 
	// 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
 
static void delay_cycles(void)
 
{
 
	uint32_t delay_cycles = 180;
 
	while(delay_cycles>0)
 
	{
 
		asm("NOP");
 
		delay_cycles--;
 
	}
 
}
 
 
 
// Send a command to the radio (Blocking)
 
// Avoid calling this during code runtime as it will block for a significant period of time due to delays
 
void si446x_sendcmd(uint8_t tx_len, uint8_t* data, uint8_t doack)
 
{
 
    SI446x_SELECT;
 
 
    delay_cycles();
 
 
    uint8_t dummyrx[25];
 
    if(tx_len >=25)
 
    {
 
    	SI446x_DESELECT;
 
    	return;
 
    }
 
 
    // using transmit receive to transmit data because it actually blocks until the data is sent
 
    // an additional byte is added on to the transmission so we can receive the CTS byte
 
 
    HAL_StatusTypeDef res = HAL_SPI_TransmitReceive(&hspi1, data, dummyrx, tx_len+1, SI446x_TIMEOUT);
 
    volatile HAL_StatusTypeDef res = HAL_SPI_TransmitReceive(&hspi1, data, dummyrx, tx_len+1, SI446x_TIMEOUT);
 
 
    if(res != HAL_OK)
 
    {
 
    	SI446x_DESELECT;
 
    	return;
 
    }
 
 
    SI446x_DESELECT;
 
 
    // If checking for the ACK, perform a SPI read and see if the command was acknowledged
 
    if(doack)
 
    {
 
		delay_cycles();
 
 
		SI446x_SELECT;
 
 
		int reply = 0x00;
 
		uint8_t tx_requestack[2];
 
		tx_requestack[0] = SI446x_CMD_READ_CMD_BUFF;
 
		tx_requestack[1] = 0x00;
 
 
		uint16_t attempts = 0;
 
		volatile uint16_t attempts = 0;
 
 
		// Keep trying receive until it returns 0xFF (successful ACK)
 
		while (reply != 0xFF)
 
		{
 
			// Attempt to receive two bytes from the Si446x which should be an ACK
 
			uint8_t tmprx[2] = {0,0};
 
			res = HAL_SPI_TransmitReceive(&hspi1, tx_requestack, tmprx, 2, SI446x_TIMEOUT);
 
			if(res != HAL_OK)
 
			{
 
				//error_assert_silent(ERR_VHF_SPIBUSY);
 
		    	break; // Break out, deinit, and exit
 
			}
 
			reply = tmprx[1];
 
 
			// Cycle chip select line on and off
 
			if (reply != 0xFF)
 
			{
 
				delay_cycles();
 
				SI446x_DESELECT;
 
				delay_cycles();
 
				SI446x_SELECT;
 
				delay_cycles();
 
				//HAL_GPIO_TogglePin(LED_ACT);
 
			}
 
 
			// Maximum number of attempts exceeded
 
			if(attempts > 1024)
 
			{
 
				//error_assert_silent(ERR_VHF_TIMEOUT);
 
				volatile uint32_t test = 344;
 
				break; // Break out, deinit and exit
 
			}
 
			attempts++;
 
		}
 
    }
 
 
    // Turn off activity LED
 
    //HAL_GPIO_WritePin(LED_ACT, GPIO_PIN_RESET);
 
 
    SI446x_DESELECT;
 
    delay_cycles();
 
}
 
 
 
// Set transmit frequency of Si446x
 
void si446x_setchannel(uint32_t frequency)
 
{
 
 
    // Set the output divider according to recommended ranges given in si446x datasheet
 
    uint32_t outdiv = 4;
 
    uint32_t band = 0;
 
    if (frequency < 705000000UL) { outdiv = 6;  band = 1;};
 
    if (frequency < 525000000UL) { outdiv = 8;  band = 2;};
 
    if (frequency < 353000000UL) { outdiv = 12; band = 3;};
 
    if (frequency < 239000000UL) { outdiv = 16; band = 4;};
 
    if (frequency < 177000000UL) { outdiv = 24; band = 5;};
 
 
    uint32_t f_pfd = 2 * SI446x_VCXO_FREQ / outdiv;
 
 
    uint32_t n = ((uint32_t)(frequency / f_pfd)) - 1;
 
 
    float ratio = (float)frequency / (float)f_pfd;
 
    float rest  = ratio - (float)n;
 
 
    uint32_t m = (uint32_t)(rest * 524288UL);
 
 
    // Set the band parameter
 
    uint32_t sy_sel = 8;
 
    uint8_t set_band_property_command[] = {SI446x_CMD_SET_PROPERTY, 0x20, 0x01, 0x51, (band + sy_sel)};
 
    si446x_sendcmd(5, set_band_property_command, SI446x_CHECK_ACK);
 
 
    // Set the pll parameters
 
    uint32_t m2 = m / 0x10000;
 
    uint32_t m1 = (m - m2 * 0x10000) / 0x100;
 
    uint32_t m0 = (m - m2 * 0x10000 - m1 * 0x100);
 
 
    // Assemble parameter string
 
    uint8_t set_frequency_property_command[] = {SI446x_CMD_SET_PROPERTY, 0x40, 0x04, 0x00, n, m2, m1, m0};
 
    si446x_sendcmd(8, set_frequency_property_command, SI446x_CHECK_ACK);
 
 
    // Set frequency deviation
 
    // ...empirically 0xF9 looks like about 5khz. Sketchy.
 
 
    //                           set prop   group     numprops  startprop   data                     // Was 0x0F 00 for ~40kHz dev, switched to 56khzish? dev
 
 
    //2DF5 is correct for 56khz
 
    uint8_t set_frequency_separation[] = {SI446x_CMD_SET_PROPERTY, 0x20,     0x03,      0x0a,     0x00, 0x03, 0x00};
 
    si446x_sendcmd(7, set_frequency_separation, SI446x_CHECK_ACK);
 
 
}
 
 
 
// Turn CW transmit on
 
void si446x_cw_on(void)
 
{
 
    // Change to TX state
 
	uint8_t change_state_command[] = {SI446x_CMD_CHANGE_STATE, 0x07};
 
    si446x_sendcmd(2, change_state_command, SI446x_CHECK_ACK);
 
    si446x_cw_status = 1;
 
}
 
 
 
// Turn CW transmit off
 
void si446x_cw_off(void)
 
{
 
    // Change to ready state
 
	uint8_t change_state_command[] = {SI446x_CMD_CHANGE_STATE, 0x03};
 
    si446x_sendcmd(2, change_state_command, SI446x_CHECK_ACK);
 
    si446x_cw_status = 0;
 
}
 
 
 
// Returns 1 if CW is on or 0 if CW is off
 
inline uint8_t si446x_tx_status(void)
 
{
 
	return si446x_cw_status;
 
}
 
 
 
// Initialize SPI port for generation of direct modulation for Si446x
 
static void __init_spi1(void)
 
{
 
 
	GPIO_InitTypeDef GPIO_InitStruct;
 
 
	// GPIO: VHF chip select
 
	GPIO_InitStruct.Pin = SI446x_CS_PIN;
 
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 
	GPIO_InitStruct.Pull = GPIO_NOPULL;
 
	GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
 
	HAL_GPIO_Init(SI446x_CS_PORT, &GPIO_InitStruct);
 
	SI446x_DESELECT;
 
 
	// SPI pins
 
	__SPI1_CLK_ENABLE();
 
	GPIO_InitStruct.Pin = SI446x_SCK_PIN|SI446x_MOSI_PIN|SI446x_MOSI_PIN;
 
	GPIO_InitStruct.Pin = SI446x_SCK_PIN|SI446x_MOSI_PIN|SI446x_MISO_PIN;
 
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 
	GPIO_InitStruct.Pull = GPIO_NOPULL;
 
	GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
 
	GPIO_InitStruct.Alternate = GPIO_AF0_SPI1;
 
	HAL_GPIO_Init(SI446x_SCK_PORT, &GPIO_InitStruct);
 
 
	// SPI peripheral
 
	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; // Double-check, this is usually high, but might be low for this chip
 
	hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; // was 1edge before (rising edge of clock)
 
	hspi1.Init.NSS = SPI_NSS_SOFT;
 
	hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
 
	hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
 
	hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
 
	hspi1.Init.TIMode = SPI_TIMODE_DISABLED;
 
	hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
 
	hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLED;
 
	HAL_SPI_Init(&hspi1);
 
}
 
 
 
// Place the Si446x into shutdown
 
void si446x_shutdown(void)
 
{
 
    HAL_GPIO_WritePin(SI446x_SHUTDOWN, GPIO_PIN_SET);
 
}
 
 
 
// Wake up the Si446x from shutdown
 
void si446x_wakeup(void)
 
{
 
    HAL_GPIO_WritePin(SI446x_SHUTDOWN, GPIO_PIN_RESET);
 
}
 
 
 
// Accessor for SPI1  handle
 
SPI_HandleTypeDef* spi1_get(void)
 
{
 
	return &hspi1;
 
}
Libraries/Si446x/si446x.h
Show inline comments
 
#ifndef SI446X_H
 
#define SI446X_H
 
 
#include "stm32f0xx_hal.h"
 
 
 
// Hardware Options ///////////////////
 
 
// Timeout for blocking writes
 
#define SI446x_TIMEOUT 10
 
#define SI446x_TIMEOUT 50
 
 
// Crystal/oscillator frequency
 
#define SI446x_VCXO_FREQ  26000000UL
 
#define SI446x_SPI SPI1
 
 
// GPIO assignments
 
#define SI446x_CS_PORT GPIOA
 
#define SI446x_CS_PIN GPIO_PIN_15
 
 
#define SI446x_GPIO_PORT GPIOA
 
#define SI446x_GPIO_PIN GPIO_PIN_10
 
 
#define SI446x_SHUTDOWN_PORT GPIOA
 
#define SI446x_SHUTDOWN_PIN GPIO_PIN_9
 
 
#define SI446x_MOSI_PORT GPIOB
 
#define SI446x_MOSI_PIN GPIO_PIN_5
 
 
#define SI446x_MISO_PORT GPIOB
 
#define SI446x_MISO_PIN GPIO_PIN_4
 
 
#define SI446x_SCK_PORT GPIOB
 
#define SI446x_SCK_PIN GPIO_PIN_3
 
 
 
#define SI446x_TCXO_EN_PORT GPIOA
 
#define SI446x_TCXO_EN_PIN GPIO_PIN_8
 
 
 
///////////////////////////////////////
 
 
 
// Registers /////////////////////////
 
#define SI446x_CMD_POWER_UP 0x02
 
#define SI446x_CMD_NOP 0x00
 
#define SI446x_CMD_PART_INFO 0x01
 
#define SI446x_CMD_FUNC_INFO 0x10
 
#define SI446x_CMD_SET_PROPERTY 0x11
 
#define SI446x_CMD_GET_PROPERTY 0x12
 
#define SI446x_CMD_GPIO_PIN_CFG 0x13
 
#define SI446x_CMD_GET_ADC_READING 0x14
 
#define SI446x_CMD_FIFO_INFO 0x15
 
#define SI446x_CMD_PACKET_INFO 0x16
 
#define SI446x_CMD_IRCAL 0x17
 
#define SI446x_CMD_PROTOCOL_CFG 0x18
 
#define SI446x_CMD_GET_INT_STATUS 0x20
 
#define SI446x_CMD_GET_PH_STATUS 0x21
 
#define SI446x_CMD_GET_MODEM_STATUS 0x22
 
#define SI446x_CMD_GET_CHIP_STATUS 0x23
 
#define SI446x_CMD_START_TX 0x31
 
#define SI446x_CMD_START_RX 0x32
 
#define SI446x_CMD_REQUEST_DEVICE_STATE 0x33
 
#define SI446x_CMD_CHANGE_STATE 0x34
 
#define SI446x_CMD_READ_CMD_BUFF 0x44
 
#define SI446x_CMD_FRR_A_READ 0x50
 
#define SI446x_CMD_FRR_B_READ 0x51
 
#define SI446x_CMD_FRR_C_READ 0x53
 
#define SI446x_CMD_FRR_D_READ 0x57
 
#define SI446x_CMD_WRITE_TX_FIFO 0x66
 
#define SI446x_CMD_READ_RX_FIFO 0x77
 
#define SI446x_CMD_RX_HOP 0x36
 
 
// GPIO pin configuration options
 
#define SI446x_GPIO_NOCHANGE 0
 
#define SI446x_GPIO_LOW 2
 
#define SI446x_GPIO_HIGH 3
 
#define SI446x_GPIO_INPUT 4
 
#define SI446x_GPIO_TXFIFO_LOW 35
 
#define SI446x_GPIO_TXENABLED 32
 
 
// GPIO pin definitions
 
#define SI446x_GPIO0 0
 
#define SI446x_GPIO1 1
 
#define SI446x_GPIO2 2
 
#define SI446x_GPIO3 3
 
 
// Property MOD_TYPE parameters
 
#define SI446x_MOD_TYPE_REGISTER_GROUP 0x20
 
#define SI446x_MOD_TYPE_REGISTER_PROP 0x00
 
#define SI446x_MOD_TYPE_CW    0
 
#define SI446x_MOD_TYPE_OOK   1
 
#define SI446x_MOD_TYPE_2FSK  2
 
#define SI446x_MOD_TYPE_2GFSK 3
 
#define SI446x_MOD_TYPE_4FSK  4
 
#define SI446x_MOD_TYPE_4GFSK 5
 
 
#define SI446x_MOD_TYPE_SOURCE_PACKETHANDLER (0<<3)
 
#define SI446x_MOD_TYPE_SOURCE_DIRECTMODE    (1<<3)
 
#define SI446x_MOD_TYPE_SOURCE_PSEUDORANDOM  (2<<3)
 
 
#define SI446x_MOD_TYPE_DIRECT_SYNCH (0<<7)
 
#define SI446x_MOD_TYPE_DIRECT_ASYNCH (1<<7)
 
 
#define SI446x_MOD_TYPE_DIRECT_SOURCE_GPIO0 (0<<5)
 
#define SI446x_MOD_TYPE_DIRECT_SOURCE_GPIO1 (1<<5)
 
#define SI446x_MOD_TYPE_DIRECT_SOURCE_GPIO2 (2<<5)
Libraries/aprs/afsk.c
Show inline comments
 
@@ -182,125 +182,121 @@ uint8_t afsk_request_cwoff(void)
 
        return 1;
 
    }
 
    else
 
    {
 
        return 0;
 
    }
 
}
 

	
 
volatile uint32_t freqctr = 0;
 

	
 
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
 
{
 
	if (go) {
 
			if (packet_pos == afsk_packet_size)
 
			{
 
					request_cwoff = 1;
 
					//gpio_toggle(GPIOB, GPIO0);
 
					//gpio_toggle(GPIOB, GPIO7);
 
					go = 0;         // End of transmission
 
					afsk_timer_stop();  // Disable modem
 
					return; // done
 
			}
 

	
 
			// If sent SAMPLES_PER_BAUD already, go to the next bit
 
			if (current_sample_in_baud == 0)  // Load up next bit
 
			{
 
					if ((packet_pos & 7) == 0) // Load up next byte
 
					{
 
							current_byte = afsk_packet[packet_pos >> 3];
 
					}
 
					else
 
					{
 
							current_byte = current_byte / 2;  // ">>1" forces int conversion
 
					}
 
					if ((current_byte & 1) == 0)
 
					{
 
							// Toggle tone (1200 <> 2200)
 
							phasedelta ^= (PHASE_DELTA_1200 ^ PHASE_DELTA_2200);
 
					}
 
			}
 

	
 
			phase += phasedelta;
 
			uint8_t s = afsk_read_sample((phase >> 7) & (TABLE_SIZE - 1));
 

	
 
			afsk_output_sample(s); //real afsk
 

	
 
			if(++current_sample_in_baud == SAMPLES_PER_BAUD)
 
			{
 
					current_sample_in_baud = 0;
 
					packet_pos++;
 
			}
 

	
 
	}
 
}
 

	
 

	
 
void afsk_timer_start()
 
{
 
    // Clear the overflow flag, so that the interrupt doesn't go off
 
    // immediately and overrun the next one (p.163).
 
    // Enable interrupt when TCNT2 reaches TOP (0xFF) (p.151, 163)
 
    //nvic_enable_irq(NVIC_TIM1_CC_IRQ);
 
//	HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);
 
	HAL_NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
 
	__HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE);
 
	HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_3);
 

	
 
    //timer_enable_counter(TIM1);
 
}
 

	
 
void afsk_timer_stop()
 
{
 
	// Resting duty cycle
 
	// Output 0v (could be 255/2, which is 0v after coupling... doesn't really matter)
 
	//OCR2A = 0x80;
 

	
 
	// Disable playback interrupt
 
	//TIMSK2 &= ~_BV(TOIE2);
 
    //nvic_disable_irq(NVIC_TIM1_CC_IRQ);
 
//	HAL_NVIC_DisableIRQ(TIM1_CC_IRQn);
 
//	HAL_NVIC_DisableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
 
	HAL_TIM_PWM_Stop_IT(&htim1, TIM_CHANNEL_3);
 
    //timer_disable_counter(TIM1);
 
}
 

	
 

	
 
// External
 

	
 
void afsk_start(void)
 
{
 
	phasedelta = PHASE_DELTA_1200;
 
	phase = 0;
 
	packet_pos = 0;
 
	current_sample_in_baud = 0;
 
	go = 1;
 

	
 
    // Wake up and configure radio
 
    //si446x_prepare();
 
    HAL_Delay(100);
 

	
 
	// Key the radio
 
	si446x_cw_on();
 

	
 
	// Start transmission
 
	afsk_timer_start();
 
}
 

	
 
uint8_t afsk_busy(void)
 
{
 
	return go;
 
}
 

	
 
void afsk_send(const uint8_t *buffer, uint16_t len)
 
{
 
	afsk_packet_size = len;
 
	afsk_packet = buffer;
 
}
 

	
 
TIM_HandleTypeDef* afsk_timer_gethandle(void)
 
{
 
	return &htim1;
 
}
 

	
 

	
 
// vim:softtabstop=4 shiftwidth=4 expandtab 
Source/main.c
Show inline comments
 
//
 
// mBuoy Depth Select Firmware
 
// Copyright 2015 SeaLandAire Technologies
 
//
 
 
#include "config.h"
 
#include "error.h"
 
#include "system/gpio.h"
 
#include "system/sysclk.h"
 
#include "system/watchdog.h"
 
#include "system/uart.h"
 
#include "stm32f0xx_hal.h"
 
#include "si446x/si446x.h"
 
#include "aprs/aprs.h"
 
#include "aprs/afsk.h"
 
#include "gps.h"
 
 
 
int main(void)
 
{
 
  hal_init();
 
  sysclock_init();
 
  gpio_init();
 
 
 
  afsk_init();
 
  si446x_init();
 
  gps_poweron();
 
 
  // Software timers
 
  uint32_t last_led = HAL_GetTick();
 
 
  while (1)
 
  {
 
	  // Blink LEDs
 
	  if(HAL_GetTick() - last_led > 1500)
 
	  if(HAL_GetTick() - last_led > 50)
 
	  {
 
		  gps_update_data();
 
		  aprs_send();
 
		  while(afsk_busy());
 
 
		  last_led = HAL_GetTick();
 
	  }
 
 
	  if(afsk_request_cwoff())
 
		  si446x_cw_off();
 
 
	  // High-frequency function calls
 
//	  gpio_process_shutdown();
 
//	  watchdog_feed();
 
  }
 
}
 
0 comments (0 inline, 0 general)