void RadioSi446x::start_tx() { // W2CXM Debug - overwrite power level char set_pa_power_lvl_command[] = {0x11, 0x22, 0x01, 0x01, 0x7f}; SendCmdReceiveAnswer(5, 1, set_pa_power_lvl_command); char change_state_command[] = {0x34, 0x07}; // Change to TX state SendCmdReceiveAnswer(2, 1, change_state_command); }
// Config reset ---------------------------------------------------------- void RadioSi446x::reset(void) { digitalWrite(VCXO_ENABLE_PIN,HIGH); // Serial.println("VCXO is enabled"); delay(200); digitalWrite(RADIO_SDN_PIN, HIGH); // active high shutdown = reset delay(200); digitalWrite(RADIO_SDN_PIN, LOW); // booting // Serial.println("Radio is powered up"); // Start talking to the Si446X radio chip const char PART_INFO_command[] = {0x01}; // Part Info SendCmdReceiveAnswer(1, 9, PART_INFO_command); // Serial.println("Part info was checked"); //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); //POWER_UP const char init_command[] = {0x02, 0x01, 0x01, x3, x2, x1, x0};// no patch, boot main app. img, FREQ_VCXO, return 1 byte SendCmdReceiveAnswer(7, 1 ,init_command); // Serial.println("Radio booted"); const char get_int_status_command[] = {0x20, 0x00, 0x00, 0x00}; // Clear all pending interrupts and get the interrupt status back SendCmdReceiveAnswer(4, 9, get_int_status_command); // Serial.println("Radio ready"); const char gpio_pin_cfg_command[] = {0x13, 0x02, 0x02, 0x02, 0x02, 0x08, 0x11, 0x00}; // Set all GPIOs LOW; Link NIRQ to CTS; Link SDO to MISO; Max drive strength SendCmdReceiveAnswer(8, 8, gpio_pin_cfg_command); // Serial.println("LEDs should be switched off at this point"); setFrequency(active_freq); // Serial.println("Frequency set"); setModem(); // Serial.println("CW mode set"); tune_tx(); // Serial.println("TX tune"); }
void reset(void) { gpio_set_value(RADIO_SDN, 1); mdelay(10); gpio_set_value(RADIO_SDN, 0); mdelay(10); u8 buff[10]; //POWER_UP /* printk(KERN_ALERT "Set CS to 1 \n"); cs_high(); printk(KERN_ALERT "get CS %d \n",gpio_get_value(SSpin)); mdelay(5000); printk(KERN_ALERT "Set CS to 0 \n"); cs_low(); printk(KERN_ALERT "get CS %d \n",gpio_get_value(SSpin)); mdelay(5000); printk(KERN_ALERT "Set CS to 1 \n"); cs_high(); printk(KERN_ALERT "get CS %d \n",gpio_get_value(SSpin)); mdelay(5000); printk(KERN_ALERT "Set CS to 0 \n"); cs_low(); printk(KERN_ALERT "get CS %d \n",gpio_get_value(SSpin)); */ //const unsigned char init_command[] = {0x02, 0x01, 0x01, x3, x2, x1, x0};// no patch, boot main app. img, FREQ_VCXO, return 1 byte u8 init_command[] = { RF_POWER_UP }; SendCmdReceiveAnswer(7, 1, init_command, buff); mdelay(20); //ppp(buff, 1); SendCmdReceiveAnswer(7, 1, init_command, buff); mdelay(20); u8 PART_INFO_command[] = { 0x01 }; // Part Info SendCmdReceiveAnswer(1, 9, PART_INFO_command, buff); //ppp(buff, 9); u8 get_int_status_command[] = { 0x20, 0x00, 0x00, 0x00 }; // Clear all pending interrupts and get the interrupt status back SendCmdReceiveAnswer(4, 9, get_int_status_command, buff); //ppp(buff, 9); //const char gpio_pin_cfg_command[] = {0x13, 0x02, 0x02, 0x02, 0x02, 0x08, 0x11, 0x00}; // Set all GPIOs LOW; Link NIRQ to CTS; Link SDO to MISO; Max drive strength // u8 gpio_pin_cfg_command[] = { 0x13, 0x14, 0x02, 0x21, 0x20, // 0x27, 0x0b, 0x00 }; // SendCmdReceiveAnswer(8, 8, gpio_pin_cfg_command, buff); // //ppp(buff, 8); // setRFParameters(); fifo_reset(); }
void Si446x::sendFrequencyToSi446x(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; // char set_band_property_command[] = {0x11, 0x20, 0x01, 0x51, (band + sy_sel)}; // // send parameters SendCmdReceiveAnswer(5, 1, 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 char set_frequency_property_command[] = {0x11, 0x40, 0x06, 0x00, n, m2, m1, m0, c1, c0}; // send parameters SendCmdReceiveAnswer(10, 1, set_frequency_property_command); // Set the Power char set_pa_pwr_lvl_property_command[] = {0x11, 0x22, 0x01, 0x01, active_level}; // send parameters SendCmdReceiveAnswer(5, 1, set_pa_pwr_lvl_property_command); }
//u8 test[300]; //void spi_write_fifo(unsigned char * data, int len) { // int j; ///* //// test[0] = WRITE_TX_FIFO; //// memcpy(test+1, data, len); //// mutex_lock(&mutex_spi); //// printk(KERN_ALERT "spi_write_fifo: write %d\n", len); // cs_low(); // u8 cmd = WRITE_TX_FIFO; // spidev_global.buffer = &cmd; // spidev_sync_write(&spidev_global, 1); //// for (j = 0; j < len; j++) { //// cmd = data[j]; //// spidev_sync_write(&spidev_global, 1); //// } // spidev_global.buffer = data; // spidev_sync_write(&spidev_global, len); // cs_high(); // //// mutex_unlock(&mutex_spi); // */ // ssize_t ret; // u8 cmd = WRITE_TX_FIFO; // struct spi_transfer t_cmd = { // .tx_buf = &cmd, // .len = 1, // }; // struct spi_transfer t_data = { // .tx_buf = data, // .len = len, // }; // struct spi_message m; // // spi_message_init(&m); // spi_message_add_tail(&t_cmd, &m); // spi_message_add_tail(&t_data, &m); // ret = spidev_sync(spidev_global, &m); //} void spi_write_fifo(unsigned char * data, int len) { int j; ssize_t ret; u8 cmd = 0x66; struct spi_transfer t_cmd = { .tx_buf = &cmd, .len = 1, .cs_change = 0, }; struct spi_transfer t_data = { .tx_buf = data, .len = len, .cs_change = 0, }; struct spi_message m; spi_message_init(&m); spi_message_add_tail(&t_cmd, &m); spi_message_add_tail(&t_data, &m); cs_low(); ret = spidev_sync(&spidev_global, &m); cs_high(); } void spi_read_fifo(unsigned char * st, int len) { int j; // mutex_lock(&mutex_spi); cs_low(); u8 cmd = READ_RX_FIFO; // u8 ret; spidev_global.buffer = &cmd; spidev_sync_write(&spidev_global, 1); cmd = 0xff; // for (j = 0; j < len; j++) { // spidev_sync_transfer(&spidev_global, &cmd, &(st[j]), 1); // // } spidev_global.buffer = st; spidev_sync_read(&spidev_global,len); cs_high(); // mutex_unlock(&mutex_spi); //Serial.println(); // unsigned char p[] = {READ_RX_FIFO}; // SendCmdReceiveAnswer(1,payload_length,p); } void get_fifo_info(u8 *rx) // 复位发射和接收 FIFO { // u8 rx[10]; unsigned char p[2]; p[0] = FIFO_INFO; p[1] = 0x00; SendCmdReceiveAnswer(2, 3, p, rx); // spi_write(2,p); }
void get_ph_status(u8 *rx){ unsigned char p[2]; p[0] = GET_PH_STATUS; p[1] = 0xfb; SendCmdReceiveAnswer(2, 3, p, rx); }
void get_modem_status(u8 *rx){ unsigned char p[2]; p[0] = GET_MODEM_STATUS; p[1] = 0xff; SendCmdReceiveAnswer(2, 4, p, rx); }
u8 get_device_state(){ u8 p[2], rx[2]; p[0] = REQUEST_DEVICE_STATE; p[1] = 0x00; SendCmdReceiveAnswer(2, 3, p, rx); return rx[1]; }
void Si446x::start_tx(char channel) { // char change_state_command[] = {0x34, 0x07}; // Change to TX state // SendCmdReceiveAnswer(2, 1, change_state_command); //tune_tx(); char start_tx_command[] = {0x31, channel, 0x30, 0x00, 0x00, 0x00}; SendCmdReceiveAnswer(6, 1, start_tx_command); }
void RadioSi446x::setModem() { // Set to CW mode // Serial.println("Setting modem into CW mode"); char set_modem_mod_type_command[] = {0x11, 0x20, 0x01, 0x00, 0x00}; SendCmdReceiveAnswer(5, 1, set_modem_mod_type_command); }
void RadioSi446x::setFrequency(unsigned long freq) { // Set the output divider according to recommended ranges given in Si446x datasheet int outdiv = 4; 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; // char set_band_property_command[] = {0x11, 0x20, 0x01, 0x51, (band + sy_sel)}; // // send parameters SendCmdReceiveAnswer(5, 1, 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); // assemble parameter string //char set_frequency_property_command[] = {0x11, 0x40, 0x04, 0x00, n, m2, m1, m0}; // send parameters //SendCmdReceiveAnswer(8, 1, set_frequency_property_command); //W2CXM - suggestions from aadamson const char set_freq_control_inte[] = {0x11, 0x40, 0x08, 0x00, n, m2, m1, m0, 0x0B, 0x61, 0x20, 0xFA}; SendCmdReceiveAnswer(12, 1, set_freq_control_inte); //W2CXM ^^^^ }
void Si446x::setModem() { // Set to CW mode //Serial.println("Setting modem into direct asynchronous 2FSK mode using GPIO0"); char set_modem_mod_type_command[] = {0x11, 0x20, 0x01, 0x00, 0b10001010}; SendCmdReceiveAnswer(5, 1, set_modem_mod_type_command); }
void clr_packet_rx_pend(void) { u8 p[2]; u8 p2[3]; p[0] = GET_PH_STATUS; // p[1] = 0xef; p[1] = 0x20;//leave the PACKET_SENT_PEND_CLR alone // spi_write_cmd(2, p); SendCmdReceiveAnswer(2,3,p,p2); }
void RadioSi446x::ptt_off() { stop_tx(); si446x_powerlevel = 0; // turn off the blue LED (GPIO2) char gpio_pin_cfg_command0[] = {0x13, 0x02, 0x02, 0x02, 0x02, 0x08, 0x0b, 0x00}; // Set all GPIOs LOW; Link NIRQ to CTS; Link SDO to MISO; Max drive strength SendCmdReceiveAnswer(8, 1, gpio_pin_cfg_command0); digitalWrite(RADIO_SDN_PIN, HIGH); // active high = shutdown //digitalWrite(VCXO_ENABLE_PIN, LOW); //keep enabled for now }
void RadioSi446x::ptt_on() { digitalWrite(VCXO_ENABLE_PIN, HIGH); reset(); // turn on the blue LED (GPIO2) to indicate TX char gpio_pin_cfg_command2[] = {0x13, 0x02, 0x02, 0x03, 0x02, 0x08, 0x0b, 0x00}; // Set GPIO2 HIGH; Link NIRQ to CTS; Link SDO to MISO; Max drive strength SendCmdReceiveAnswer(8, 1, gpio_pin_cfg_command2); start_tx(); si446x_powerlevel = 1023; }
void get_interrupt_status(u8* p2) // 中断 { unsigned char p[4]; p[0] = GET_INT_STATUS; p[1] = 0xfb; p[2] = 0x7f; p[3] = 0x7f; SendCmdReceiveAnswer(4,9,p,p2); // spi_write_cmd(4, p); //spi_read(9,GET_INT_STATUS); }
//u16 get_packet_info() //{ // unsigned char p[6]; // unsigned char p2[3]; // u16 bLen; // // p[0] = CMD_PACKET_INFO; // p[1] = 0x00; // p[2] = 0x00; // p[3] = 0x00; // p[4] = 0x00; // p[5] = 0x00; // SendCmdReceiveAnswer(1,3,p,p2); // bLen = ((u16)p2[1] << 8) | (u16)p2[2]; // return bLen; //} u8 get_packet_info(void) { unsigned char p[3]; unsigned char p2[3]; p[0] = PACKET_INFO ; // p[1] = 0x00 ; // 通道0 // p[2] = 0x00; // p[3] = 0x00; // p[4] = 0x00; // p[5] = 0x00; SendCmdReceiveAnswer(1, 3, p, p2); // ppp(p2,3); return p2[2]; }
void Si446x::setDeviation(unsigned long deviation) { //Make sure that Si446x::sendFrequencyToSi446x() was called before this function, so that we have set the global variable 'outdiv' properly //outdiv = 8; float units_per_hz = (( 0x40000 * outdiv ) / (float)VCXO_FREQ); // Set deviation for RTTY unsigned long modem_freq_dev = (unsigned long)(units_per_hz * deviation / 2.0 ); unsigned long mask = 0b11111111; char modem_freq_dev_0 = mask & modem_freq_dev; char modem_freq_dev_1 = mask & (modem_freq_dev >> 8); char modem_freq_dev_2 = mask & (modem_freq_dev >> 16); char set_modem_freq_dev_command[] = {0x11, 0x20, 0x03, 0x0A, modem_freq_dev_2, modem_freq_dev_1, modem_freq_dev_0}; SendCmdReceiveAnswer(7, 1, set_modem_freq_dev_command); }
void RadioSi446x::tune_tx() { char change_state_command[] = {0x34, 0x05}; // Change to TX tune state SendCmdReceiveAnswer(2, 1, change_state_command); }
void RadioSi446x::stop_tx() { char change_state_command[] = {0x34, 0x03}; // Change to Ready state SendCmdReceiveAnswer(2, 1, change_state_command); }
// Config reset ---------------------------------------------------------- void RadioSi446x::reset(void) { digitalWrite(VCXO_ENABLE_PIN,HIGH); // Serial.println("VCXO is enabled"); delay(200); digitalWrite(RADIO_SDN_PIN, HIGH); // active high shutdown = reset delay(200); digitalWrite(RADIO_SDN_PIN, LOW); // booting // Serial.println("Radio is powered up"); // Start talking to the Si446X radio chip const char PART_INFO_command[] = {0x01}; // Part Info SendCmdReceiveAnswer(1, 9, PART_INFO_command); // Serial.println("Part info was checked"); //W2CXM - Suggested that we add this delay by aadmson delay(15); //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); //POWER_UP const char init_command[] = {0x02, 0x01, 0x01, x3, x2, x1, x0};// no patch, boot main app. img, FREQ_VCXO, return 1 byte SendCmdReceiveAnswer(7, 1 ,init_command); // Serial.println("Radio booted"); const char get_int_status_command[] = {0x20, 0x00, 0x00, 0x00}; // Clear all pending interrupts and get the interrupt status back SendCmdReceiveAnswer(4, 9, get_int_status_command); // Serial.println("Radio ready"); const char gpio_pin_cfg_command[] = {0x13, 0x02, 0x02, 0x02, 0x02, 0x08, 0x0b, 0x00}; // Set all GPIOs LOW; Link NIRQ to CTS; Link SDO to MISO; Max drive strength SendCmdReceiveAnswer(8, 8, gpio_pin_cfg_command); // W2CXM - Added two more initializations per aadamson const char set_global_config1[] = {0x11, 0x00, 0x01, 0x03, 0x60}; SendCmdReceiveAnswer(5, 1, set_global_config1); // cliPrint("Setting special global Config 1 changes (see WDS)\n"); const char set_global_xo_tune_command[] = {0x11, 0x00, 0x01, 0x00, 0x00}; SendCmdReceiveAnswer(5, 1, set_global_xo_tune_command); // cliPrint("Setting no additional capacitance on VXCO\n"); // W2CXM ^^^^^^^^^ // Serial.println("LEDs should be switched off at this point"); setFrequency(active_freq); // Serial.println("Frequency set"); setModem(); // Serial.println("CW mode set"); tune_tx(); // Serial.println("TX tune"); }
u8 * spi_write_cmd(int byteCountTx, u8 * in_buff) { return SendCmdReceiveAnswer(byteCountTx, 0, in_buff, NULL); }
void RadioSi446x::start_tx() { char change_state_command[] = {0x34, 0x07}; // Change to TX state SendCmdReceiveAnswer(2, 1, change_state_command); }