Skip to content

Instantly share code, notes, and snippets.

@donghee
Last active July 25, 2022 08:38
Show Gist options
  • Save donghee/1a0fe13788095955eb40 to your computer and use it in GitHub Desktop.
Save donghee/1a0fe13788095955eb40 to your computer and use it in GitHub Desktop.
Test PTT from Si4463 on Fubarino mini https://github.com/seongyooncho/polarnstruments
#include <SoftSPI.h>
/*
This code based from pecanpico6 Si446x Driver by KT5TK
https://github.com/tkrahn/pecanpico5a
*/
/*
const static uint8_t SS = 30; // PIC32 SS2
const static uint8_t MOSI = 29; // PIC32 SDO2
const static uint8_t MISO = 27; // PIC32 SDI2
const static uint8_t SCK = 4; // PIC32 SCK2
*/
#define RF_GP1 3
#define RF_NIRQ 0
#define RF_SCK SCK
#define RF_MISO MISO
#define RF_MOSI MOSI
#define RF_NSEL SS
#define RF_GP3 2
#define RF_SDN 26
#define LED1 PIN_LED1
#define LED2 25
SoftSPI spi;
void Si4463_reset()
{
// Reset Radio(POR)
digitalWrite(RF_SDN, HIGH);
delay_us(10);
digitalWrite(RF_SDN, LOW);
}
void Si4463_send(int command_byte_size, uint8_t * command_bytes)
{
// Set Slave Select
spi.setSelect(HIGH);
delay_us(10);
spi.setSelect(LOW);
spi.transfer(command_byte_size, command_bytes);
// Set Slave Select
spi.setSelect(HIGH);
delay_us(20);
spi.setSelect(LOW);
// Wait CTS
int reply = 0x00;
while (reply != 0xFF)
{
spi.transfer(0x44);
reply = spi.transfer(0x44);
Serial.print(reply, HEX);
Serial.print(" ");
if (reply != 0xFF)
{
spi.setSelect(HIGH);
delay_us(10);
spi.setSelect(LOW);
}
}
spi.setSelect(HIGH);
delay_ms(50);
}
void Si4463_radio_boot()
{
// Waiting GP1=HIGH for 5ms for POR
do {
delay_ms(5);
} while (digitalRead(RF_GP1) == LOW);
// PowerUP
#define VCXO_FREQ 30000000L
// Divide VCXO_FREQ into its bytes; MSB first
unsigned int x3 = VCXO_FREQ / 0x1000000;
unsigned int x2 = (VCXO_FREQ - x3 * 0x1000000) / 0x10000;
unsigned int x1 = (VCXO_FREQ - x3 * 0x1000000 - x2 * 0x10000) / 0x100;
unsigned int x0 = (VCXO_FREQ - x3 * 0x1000000 - x2 * 0x10000 - x1 * 0x100);
uint8_t init_command[] = {0x02, 0x01, 0x01, x3, x2, x1, x0};// no patch, boot main app. img, FREQ_VCXO, return 1 byte
Si4463_send(7, init_command);
}
void Si4463_radio_ready()
{
// clear all pending interrupts
uint8_t get_int_status_command[] = {0x20, 0x00, 0x00, 0x00}; // Clear all pending interrupts and get the interrupt status back
Si4463_send(4, get_int_status_command);
}
int outdiv = 4;
unsigned int si446x_powerlevel = 0;
unsigned long active_shift = 400;
unsigned int active_level = 20;
void Si4463_set_frequency(unsigned long freq)
{
// Set the output divider according to recommended ranges given in Si446x datasheet
int band = 0;
if (freq < 705000000UL) { outdiv = 6; band = 1;};
if (freq < 525000000UL) { outdiv = 8; band = 2;};
if (freq < 353000000UL) { outdiv = 12; band = 3;};
if (freq < 239000000UL) { outdiv = 16; band = 4;};
if (freq < 177000000UL) { outdiv = 24; band = 5;};
unsigned long f_pfd = 2 * VCXO_FREQ / outdiv;
unsigned int n = ((unsigned int)(freq / f_pfd)) - 1;
float ratio = (float)freq / (float)f_pfd;
float rest = ratio - (float)n;
unsigned long m = (unsigned long)(rest * 524288UL);
// set the band parameter
unsigned int sy_sel = 8; //
uint8_t set_band_property_command[] = {0x11, 0x20, 0x01, 0x51, (band + sy_sel)}; //
// send parameters
Si4463_send(5, set_band_property_command);
// Set the pll parameters
unsigned int m2 = m / 0x10000;
unsigned int m1 = (m - m2 * 0x10000) / 0x100;
unsigned int m0 = (m - m2 * 0x10000 - m1 * 0x100);
unsigned long channel_increment = 524288 * outdiv * active_shift / (2 * VCXO_FREQ);
char c1 = channel_increment / 0x100;
char c0 = channel_increment - (0x100 * c1);
// assemble parameter string
uint8_t set_frequency_property_command[] = {0x11, 0x40, 0x06, 0x00, n, m2, m1, m0, c1, c0};
// send parameters
Si4463_send(10, set_frequency_property_command);
// Set the Power
uint8_t set_pa_pwr_lvl_property_command[] = {0x11, 0x22, 0x01, 0x01, active_level};
// send parameters
Si4463_send(5, set_pa_pwr_lvl_property_command);
}
void Si4463_set_modem()
{
// Set to CW mode
uint8_t set_modem_mod_type_command[] = {0x11, 0x20, 0x01, 0x00, 0x00};
Si4463_send(5, set_modem_mod_type_command);
}
void Si4463_tune_tx() {
uint8_t change_state_command[] = {0x34, 0x05}; // Change to TX tune state
Si4463_send(2, change_state_command);
}
void Si4463_ptt_off() {
// Set Power 0(MIN)
uint8_t power = 0;
uint8_t set_pa_power_command[] = {0x11, 0x22, 0x01, 0x01, power};
Si4463_send(5, set_pa_power_command);
// TURN RF Switch as TX
// uPG2214TB RF Switch turn TX RF_GP0=LOW, RF_GP2=HIGH
uint8_t gpio_pin_cfg_command[] = {0x13, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00}; // Set GPIO0 as LOW, GPIO2 as HIGH. all other GPIOs do not modify; NIRQ do not modify;SDO do not modify; Max drive strength
Si4463_send(8, gpio_pin_cfg_command);
// start tx
uint8_t change_state_command[] = {0x34, 0x07}; // Change to TX state
Si4463_send(2, change_state_command);
}
void Si4463_ptt_on()
{
digitalWrite(RF_SDN, LOW);
// Set Power 127(MAX)
uint8_t power = 127;
uint8_t set_pa_power_command[] = {0x11, 0x22, 0x01, 0x01, power};
Si4463_send(5, set_pa_power_command);
// TURN RF Switch as TX
// uPG2214TB RF Switch turn TX RF_GP0=LOW, RF_GP2=HIGH
uint8_t gpio_pin_cfg_command[] = {0x13, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00}; // Set GPIO0 as LOW, GPIO2 as HIGH. all other GPIOs do not modify; NIRQ do not modify;SDO do not modify; Max drive strength
Si4463_send(8, gpio_pin_cfg_command);
// start tx mode
uint8_t change_state_command[] = {0x34, 0x07}; // Change to TX state
Si4463_send(2, change_state_command);
}
void setup()
{
// Serial
Serial.begin(9600);
// Setup GPIO
pinMode(LED1, OUTPUT);
pinMode(RF_GP1, INPUT);
pinMode(RF_NIRQ, INPUT);
pinMode(RF_SDN, OUTPUT);
// Turn off Si4463
digitalWrite(RF_SDN, HIGH);
// Setup SPI
spi.begin(RF_NSEL, RF_MOSI, RF_MISO, RF_SCK);
//spi.begin();
spi.setSpeed(250000); // 250khz
spi.setMode(SSPI_MODE0);
//spi.setDirection(SSPI_SHIFT_LEFT); // MSB
spi.setSelect(HIGH); // Do not select a slave
Serial.println("Start Serial");
// Reset Radio
Si4463_reset();
// Radio Boot
Si4463_radio_boot();
// Radio Ready and Set GPIO, Frequency, Mode
Si4463_radio_ready();
Si4463_set_frequency(460000000UL);
Si4463_set_modem();
// Set Tune TX
Si4463_tune_tx();
// Start TX
Si4463_ptt_on();
}
void loop()
{
Si4463_ptt_on();
digitalWrite(LED1, HIGH);
delay(1000);
Si4463_ptt_off();
digitalWrite(LED1, LOW);
delay(1000);
}
void delay_ms(long tick)
{
delay_us(tick * 1000);
}
void delay_us(long tick)
{
volatile int cnt;
for (cnt = 0; cnt < tick*10; cnt++) {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment