Пример #1
0
static u16 frsky_cb()
{
    if (state < FRSKY_BIND_DONE) {
        build_bind_packet_1way();
        CC2500_Strobe(CC2500_SIDLE);
        CC2500_WriteReg(CC2500_0A_CHANNR, 0x00);
        CC2500_WriteData(packet, packet[0]+1);
        state++;
        return 53460;
    }
    if (state == FRSKY_BIND_DONE) {
        state++;
        PROTOCOL_SetBindState(0);
    }
    if (state >= FRSKY_DATA1) {
        u8 chan = calc_channel();
        CC2500_Strobe(CC2500_SIDLE);
        CC2500_WriteReg(CC2500_0A_CHANNR, chan * 5 + 6);
        build_data_packet_1way();
        CC2500_WriteData(packet, packet[0]+1);
        state++;
        if (state > FRSKY_DATA5)
            state = FRSKY_DATA1;
        return 9006;
    }
        
    return 0;
}
Пример #2
0
void CC2500_SetRecvAddr(CC2500_RECV_ADDR AddrMode,u8 SpecAddr)
{
	CC2500_WriteReg(CCxxx0_ADDR,SpecAddr);	
	CC2500_WriteReg(CCxxx0_PKTCTRL1,AddrMode);//地址检查寄存器
	
	CC2500_SetRxd();
}
Пример #3
0
void CC2500_SetTxRxMode(enum TXRX_State mode)
{
    // config-cc2500 = 0x01 for swapping GDO0 and GDO2.
    int R0 = CC2500_02_IOCFG0;
    int R2 = CC2500_00_IOCFG2;
    if (Transmitter.module_config[CC2500] == CC2500_REVERSE_GD02) {
      R0 = CC2500_00_IOCFG2;
      R2 = CC2500_02_IOCFG0;
    }

    if(mode == TX_EN) {
#if RFX2401C
        CC2500_WriteReg(R0, 0x2F | 0x40);
        CC2500_WriteReg(R2, 0x2F);
#else
    // non C version (RFX2401) needs CE signal high for both RX and TX
        CC2500_WriteReg(R0, 0x2F | 0x40); // TX/RXN
        CC2500_WriteReg(R2, 0x2F | 0x40); // CE
#endif
    } else if (mode == RX_EN) {
#if RFX2401C
        CC2500_WriteReg(R0, 0x2F);
        CC2500_WriteReg(R2, 0x2F | 0x40);
#else
        CC2500_WriteReg(R0, 0x2F); // TX/RXN
        CC2500_WriteReg(R2, 0x2F | 0x40); // CE
#endif
    } else {
        CC2500_WriteReg(R0, 0x2F);
        CC2500_WriteReg(R2, 0x2F);
    }
}
Пример #4
0
// Initial register for WOR mode
void CC2500_Init_WOR(void)
{
    CC2500_SendSpiData(CCxxx0_SIDLE);
    CC2500_WriteReg(CCxxx0_WORCTRL, 0x08); // 
    CC2500_WriteReg(CCxxx0_WOREVT1, 0x2b);//43B5 500ms, 28A0 300ms 1B15 200ms
    CC2500_WriteReg(CCxxx0_WOREVT0, 0x15);// 876B 1S
    CC2500_WriteReg(CCxxx0_MCSM2, 0x03);  // RX_TIME // RX_TIME_RSSI= 1  RX_TIME_QUAL = 0
    // 0:12.5%, 1:6.25%, 2:3.125%, 3:1.563%, 4:0.781%
    CC2500_WriteReg(CCxxx0_MCSM0, 0x38);  // 频率校准方式,每4次从IDLE模式到RX模式进行一次频率合成器校准
    CC2500_SendSpiData(CCxxx0_SWORRST);
    CC2500_SendSpiData(CCxxx0_SWOR);
}
Пример #5
0
static void HITEC_CC2500_init() {
    const u8 HITEC_init_values[] = {
      /* 00 */ 0x2F, 0x2E, 0x2F, 0x07, 0xD3, 0x91, 0xFF, 0x04,
      /* 08 */ 0x45, 0x00, 0x00, 0x12, 0x00, 0x5C, 0x85, HITEC_FREQ0_VAL,
      /* 10 */ 0x3D, 0x3B, 0x73, 0x73, 0x7A, 0x01, 0x07, 0x30,
      /* 18 */ 0x08, 0x1D, 0x1C, 0xC7, 0x00, 0xB0, 0x87, 0x6B,
      /* 20 */ 0xF8, 0xB6, 0x10, 0xEA, 0x0A, 0x00, 0x11,
    };

    CC2500_Strobe(CC2500_SIDLE);

    for (u8 i = 0; i < 39; ++i)
        CC2500_WriteReg(i, HITEC_init_values[i]);

    CC2500_SetTxRxMode(TX_EN);
    CC2500_SetPower(Model.tx_power);
}
Пример #6
0
void CC2500_SetPower(int power)
{
    const unsigned char patable[8]=
    {
        0xC5,  // -12dbm
        0x97, // -10dbm
        0x6E, // -8dbm
        0x7F, // -6dbm
        0xA9, // -4dbm
        0xBB, // -2dbm
        0xFE, // 0dbm
        0xFF // 1.5dbm
    };
    if (power > 7)
        power = 7;
    CC2500_WriteReg(CC2500_3E_PATABLE,  patable[power]);
}
Пример #7
0
void CC2500_SetTxRxMode(enum TXRX_State mode)
{
    if(mode == TX_EN) {
        CC2500_WriteReg(CC2500_02_IOCFG0, 0x2F | 0x40);
        CC2500_WriteReg(CC2500_00_IOCFG2, 0x2F);
    } else if (mode == RX_EN) {
        CC2500_WriteReg(CC2500_02_IOCFG0, 0x2F);
        CC2500_WriteReg(CC2500_00_IOCFG2, 0x2F | 0x40);
    } else {
        CC2500_WriteReg(CC2500_02_IOCFG0, 0x2F);
        CC2500_WriteReg(CC2500_00_IOCFG2, 0x2F);
    }
}
Пример #8
0
MODULE_CALLTYPE
static u16 corona_cb() {
  // Tune frequency if it has been changed
  if (fine != (s8)Model.proto_opts[PROTO_OPTS_FREQFINE]) {
      fine = (s8)Model.proto_opts[PROTO_OPTS_FREQFINE];
      CC2500_WriteReg(CC2500_0C_FSCTRL0, fine);
  }

  if (bind_counter) {
      if (bind_counter-- == 0) PROTOCOL_SetBindState(0);
      packet_period = CORONA_build_bind_pkt();
  } else {
      packet_period = CORONA_build_packet();
  }

  // Send packet
  CC2500_WriteData(packet, packet[0]+2);
  return packet_period;
}
Пример #9
0
/* init stuff for normal RXing. */
void frsky_d8_rx_normal_init(void)
{
  CC2500_WriteReg(CC2500_REG_ADDR, (uint8_t)m_config.frsky_d8_bind_info.bind_id);
  frsky_full_cal();
  
  switch(m_config.rssi_injection_type)
  {
    default:
      num_frsky2way_channels = 8;
      break;
    case RSSI_INJECTION_AUTO:
      switch(m_config.frsky_d8_bind_info.bind_type)
      {
        default:
        case BIND_TYPE_D8:
          rssichan = 8; // inject on channel 9 by default.
          num_frsky2way_channels = 9;
          break;
      }
      break;
    case RSSI_INJECTION_NONE:
      switch(m_config.frsky_d8_bind_info.bind_type)
      {
        default:
        case BIND_TYPE_D8:
          num_frsky2way_channels = 8;
          break;
      }
      break;
    case RSSI_INJECTION_CHAN:
      rssichan = m_config.rssi_injection_chan;
      switch(m_config.frsky_d8_bind_info.bind_type)
      {
        default:
        case BIND_TYPE_D8:
          if (rssichan > 7)
            num_frsky2way_channels = rssichan + 1;
          break;
      }
      break;
  }
}
Пример #10
0
static void CORONA_rf_init() {

  CC2500_Strobe(CC2500_SIDLE);

  for (u8 i = 0; i <= 0x2E; ++i) CC2500_WriteReg(i, CORONA_init_values[i]);
  CC2500_Strobe(CC2500_SCAL);           // just duplicating stock tx
  CC2500_ReadReg(CC2500_25_FSCAL1);     // just duplicating stock tx

  if (Model.proto_opts[PROTO_OPTS_FORMAT] == FORMAT_V2) {
    CC2500_WriteReg(CC2500_0A_CHANNR, CORONA_BIND_CHANNEL_V2);
    CC2500_WriteReg(CC2500_0E_FREQ1, 0x80);
    CC2500_WriteReg(CC2500_0F_FREQ0, 0x00);
    CC2500_WriteReg(CC2500_15_DEVIATN, 0x50);
    CC2500_WriteReg(CC2500_17_MCSM1, 0x00);
    CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0x67);
    CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0xFB);
    CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0xDC);
  } else if (Model.proto_opts[PROTO_OPTS_FORMAT] == FORMAT_FDV3) {
    // Flydream receiver captures have deviation 50, tx captures show 47
    CC2500_WriteReg(CC2500_15_DEVIATN, 0x50);
  }
  
  CC2500_WriteReg(CC2500_0C_FSCTRL0, Model.proto_opts[PROTO_OPTS_FREQFINE]);
  CC2500_SetTxRxMode(TX_EN);
  CC2500_SetPower(0);   // min power for binding, set in build_packet for normal operation
}
Пример #11
0
static u16 CORONA_build_packet(void) {
  CC2500_SetPower(Model.tx_power);   // Update RF power

  if (state && (Model.proto_opts[PROTO_OPTS_FORMAT] == FORMAT_V2)) {
    // Send identifier packet for 2.65sec. This is how the RX learns the hopping table after a bind. Why it's not part of the bind like V1 is a mistery...
    // Set channel
    CC2500_WriteReg(CC2500_0A_CHANNR, 0x00);
    state--;
    packet[0]=0x07;   // 8 bytes to follow
    // Send hopping freq
    for(u8 i=0; i<CORONA_RF_NUM_CHANNELS; i++)
      packet[i+1]=hopping_frequency[i];
    // Send TX ID
    for(u8 i=0; i<CORONA_ADDRESS_LENGTH; i++)
      packet[i+4]=rx_tx_addr[i];
    packet[8]=0;
    return 6647;
  }


  // Flydream every fourth packet is identifier packet and is on channel number
  // that is last byte of rx_tx_addr
  if (fdv3_id_send) {
      fdv3_id_send = 0;
      CC2500_WriteReg(CC2500_0A_CHANNR, rx_tx_addr[CORONA_ADDRESS_LENGTH-1]);
      packet[0] = 0x07;   // 8 bytes to follow
      // Send TX ID
      for(u8 i = 0; i < CORONA_ADDRESS_LENGTH; i++)
        packet[i+1] = rx_tx_addr[i];
      // Send hopping freq
      for(u8 i = 0; i < CORONA_RF_NUM_CHANNELS; i++)
        packet[i+1+CORONA_ADDRESS_LENGTH] = hopping_frequency[i];
      packet[8] = 0;
      return 2*FDV3_CHANNEL_PERIOD;  // extra delay after id packet according to captures
  }


  // Set RF channel
  CC2500_WriteReg(CC2500_0A_CHANNR, hopping_frequency[hopping_frequency_no]);

  // Build packet
  packet[0] = 0x10;   // 17 bytes to follow
  
  // Channels
  memset(packet+9, 0x00, 4);
  for (u8 i=0; i<8; i++) { // Channel values are packed
    u16 val=convert_channel_ppm(i);
    packet[i+1] = val;
    packet[9 + (i>>1)] |= (i&0x01)?(val>>4)&0xF0:(val>>8)&0x0F;
  }

  // TX ID
  for (u8 i=0; i < CORONA_ADDRESS_LENGTH; i++)
    packet[i+13] = rx_tx_addr[i];
  
  packet[17] = 0x00;

  if (Model.proto_opts[PROTO_OPTS_FORMAT] != FORMAT_FDV3) {
      // Packet period is based on hopping
      switch (hopping_frequency_no) {
        case 0:
          packet_period = Model.proto_opts[PROTO_OPTS_FORMAT] == FORMAT_V1
                        ? 4991
                        : 4248;
          break;
        case 1: 
          packet_period = Model.proto_opts[PROTO_OPTS_FORMAT] == FORMAT_V1
                        ? 4991
                        : 4345;
          break;
        case 2: 
          packet_period = Model.proto_opts[PROTO_OPTS_FORMAT] == FORMAT_V1
                        ? 12520
                        : 13468;
          if (Model.proto_opts[PROTO_OPTS_FORMAT] == FORMAT_V2)
              packet[17] = 0x03;
          break;
      }
  }
  hopping_frequency_no++;

  if (Model.proto_opts[PROTO_OPTS_FORMAT] == FORMAT_FDV3) {
      if (hopping_frequency_no == CORONA_RF_NUM_CHANNELS) {
          fdv3_id_send = 1;
          packet_period = 6000; // extra delay before id packet according to captures
      } else {
          packet_period = FDV3_CHANNEL_PERIOD;
      }
  }

  hopping_frequency_no %= CORONA_RF_NUM_CHANNELS;
  return packet_period;
}
Пример #12
0
static void frsky_init()
{
        CC2500_Reset();

        CC2500_WriteReg(CC2500_17_MCSM1, 0x0c);
        CC2500_WriteReg(CC2500_18_MCSM0, 0x18);
        CC2500_WriteReg(CC2500_06_PKTLEN, 0xff);
        CC2500_WriteReg(CC2500_07_PKTCTRL1, 0x04);
        CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05);
        CC2500_WriteReg(CC2500_3E_PATABLE, 0xfe);
        CC2500_WriteReg(CC2500_0B_FSCTRL1, 0x08);
        CC2500_WriteReg(CC2500_0C_FSCTRL0, fine);
        CC2500_WriteReg(CC2500_0D_FREQ2, 0x5c);
        CC2500_WriteReg(CC2500_0E_FREQ1, 0x58);
        CC2500_WriteReg(CC2500_0F_FREQ0, 0x9d + course);
        CC2500_WriteReg(CC2500_10_MDMCFG4, 0xaa);
        CC2500_WriteReg(CC2500_11_MDMCFG3, 0x10);
        CC2500_WriteReg(CC2500_12_MDMCFG2, 0x93);
        CC2500_WriteReg(CC2500_13_MDMCFG1, 0x23);
        CC2500_WriteReg(CC2500_14_MDMCFG0, 0x7a);
        CC2500_WriteReg(CC2500_15_DEVIATN, 0x41);
        CC2500_WriteReg(CC2500_19_FOCCFG, 0x16);
        CC2500_WriteReg(CC2500_1A_BSCFG, 0x6c);
        CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0x43);
        CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x40);
        CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0x91);
        CC2500_WriteReg(CC2500_21_FREND1, 0x56);
        CC2500_WriteReg(CC2500_22_FREND0, 0x10);
        CC2500_WriteReg(CC2500_23_FSCAL3, 0xa9);
        CC2500_WriteReg(CC2500_24_FSCAL2, 0x0a);
        CC2500_WriteReg(CC2500_25_FSCAL1, 0x00);
        CC2500_WriteReg(CC2500_26_FSCAL0, 0x11);
        CC2500_WriteReg(CC2500_29_FSTEST, 0x59);
        CC2500_WriteReg(CC2500_2C_TEST2, 0x88);
        CC2500_WriteReg(CC2500_2D_TEST1, 0x31);
        CC2500_WriteReg(CC2500_2E_TEST0, 0x0b);
        CC2500_WriteReg(CC2500_03_FIFOTHR, 0x07);
        CC2500_WriteReg(CC2500_09_ADDR, 0x00);

        CC2500_SetTxRxMode(TX_EN);
        CC2500_SetPower(Model.tx_power);

        CC2500_Strobe(CC2500_SIDLE);    // Go to idle...
        //CC2500_WriteReg(CC2500_02_IOCFG0,   0x06);
        //CC2500_WriteReg(CC2500_0A_CHANNR, 0x06);
#if 0
        CC2500_WriteReg(CC2500_02_IOCFG0,   0x01); // reg 0x02: RX complete interrupt
        CC2500_WriteReg(CC2500_17_MCSM1,    0x0C); // reg 0x17: Stay in rx after packet complete
        CC2500_WriteReg(CC2500_18_MCSM0,    0x18); // reg 0x18: Calibrate when going from idle to rx or tx, po timeout count = 64
        CC2500_WriteReg(CC2500_06_PKTLEN,   62);   // Leave room for appended status bytes
        CC2500_WriteReg(CC2500_08_PKTCTRL0, 0x05); // reg 0x08: CRC_EN = 1, Length_config = 1 (variable length)
        CC2500_WriteReg(CC2500_3E_PATABLE,  0xFF);
        CC2500_WriteReg(CC2500_0B_FSCTRL1,  0x08); // reg 0x0B: 203 KHz IF
        CC2500_WriteReg(CC2500_0C_FSCTRL0,  0x00); // reg 0x0C

//      CC2500_WriteReg(CC2500_0D_FREQ2,    0x5C); // reg 0x0D
//      CC2500_WriteReg(CC2500_0E_FREQ1,    0x76); // reg 0x0E
//      CC2500_WriteReg(CC2500_0F_FREQ0,    0x27); // reg 0x0F
        CC2500_WriteReg(CC2500_0D_FREQ2,    0x5C); // reg 0x0D     hack: Due to a bit high xtal we shift this down by around 70 khz
        CC2500_WriteReg(CC2500_0E_FREQ1,    0x75); // reg 0x0E
        CC2500_WriteReg(CC2500_0F_FREQ0,    0x6A); // reg 0x0F
        CC2500_WriteReg(CC2500_10_MDMCFG4,  0xAA); // reg 0x10
        CC2500_WriteReg(CC2500_11_MDMCFG3,  0x39); // reg 0x11
        CC2500_WriteReg(CC2500_12_MDMCFG2,  0x11); // reg 0x12
        CC2500_WriteReg(CC2500_13_MDMCFG1,  0x23); // reg 0x13
        CC2500_WriteReg(CC2500_14_MDMCFG0,  0x7A); // reg 0x14
        CC2500_WriteReg(CC2500_15_DEVIATN,  0x42); // reg 0x15
        CC2500_WriteReg(CC2500_19_FOCCFG,   0x16); // reg 0x19
        CC2500_WriteReg(CC2500_1A_BSCFG,    0x6C); // reg 0x1A
        CC2500_WriteReg(CC2500_1B_AGCCTRL2, 0x03); // reg 0x1B
        CC2500_WriteReg(CC2500_1C_AGCCTRL1, 0x40); // reg 0x1C
        CC2500_WriteReg(CC2500_1D_AGCCTRL0, 0x91); // reg 0x1D
        CC2500_WriteReg(CC2500_21_FREND1,   0x56); // reg 0x21: Default POR value
        CC2500_WriteReg(CC2500_22_FREND0,   0x10); // reg 0x22: Default POR value
        CC2500_WriteReg(CC2500_23_FSCAL3,   0xA9); // reg 0x23: Default POR value
        CC2500_WriteReg(CC2500_24_FSCAL2,   0x05); // reg 0x24: Default POR value
        CC2500_WriteReg(CC2500_25_FSCAL1,   0x00); // reg 0x25
        CC2500_WriteReg(CC2500_26_FSCAL0,   0x11); // reg 0x26
        CC2500_WriteReg(CC2500_29_FSTEST,   0x59); // reg 0x29
        CC2500_WriteReg(CC2500_2C_TEST2,    0x88); // reg 0x2C
        CC2500_WriteReg(CC2500_2D_TEST1,    0x31); // reg 0x2D
        CC2500_WriteReg(CC2500_2E_TEST0,    0x0B); // reg 0x2E
        CC2500_WriteReg(CC2500_03_FIFOTHR,  0x0F); // reg 0x03: Use max rx fifo
        CC2500_WriteReg(CC2500_09_ADDR,     0x03); // reg 0x09: FrSky bind address is 0x0301 on channel 0
        CC2500_Strobe(CC2500_SIDLE);    // Go to idle...



        CC2500_WriteReg(CC2500_07_PKTCTRL1,0x0D);  // reg 0x07 hack: Append status, filter by address, auto-flush on bad crc, PQT=0
        CC2500_WriteReg(CC2500_0C_FSCTRL0, 0);     // Frequency offset...
        CC2500_WriteReg(CC2500_0A_CHANNR, 0);
#endif

}
Пример #13
0
void frsky_d8_rx_loop(void)
{
  // TODO: disable LNA on high power rxing
  // TODO: rssi injection (and settings)
  
  //36ms loop. rx 3 times every 9ms. then ~2ms, then tx a packet (~6ms?). then wait for next packet, continue cycle.
  static uint8_t frsky_state = FRSKY_RX1; // can be derived from counter
  static uint8_t hopchan = 0; // can be derived from counter
  static uint8_t rx_state = STATE_WILL_RX;
  static uint8_t fail_state = STATE_SEARCH;
  static uint32_t lastPktTime = 0; // time last packet was received, used mainly for failasfe.
  static uint32_t nextPktTime = 200; // time of next expected incoming packet. default: approx. 200ms startup time, to not f**k shit up, this is still hacky and shitty tho
  static uint32_t lastHopTime = 0; // time of last hop, normally every 9ms, in searchmode every 45ms. telem txing places this in the middle of its packet frame for simplicity
  static uint32_t txStartTime = 0; // time when the tx packet should start, usually 2ms after an RX3 was received.
  static uint8_t gotFirstPkt = 0;
  static uint32_t failsafeBtnTime = 0;
  static uint8_t failsafeBtnSettingStatus = 0;
  
  uint32_t time = HAL_GetTick();
  uint8_t freqoff_est;
  
  if (m_config.frsky_d8_bind_info.bind_type == BIND_TYPE_NONE)
  {
    /* do nothing if not bound. */
    return;
  }
  
  switch (rx_state)
  {
    case STATE_WILL_RX:
      frsky_rx_enable(hopchan);
      rx_state = STATE_RXING;
      break;
      /* end STATE_WILL_RX */
    
    case STATE_RXING:
      if (frsky_d8_rx_getpkt() != 0)
      {
        rx_state = STATE_RXD;
        break;
      }
      
      switch (fail_state)
      {
        case STATE_RUNNING:
          /* If we expected a packet and didn't get it, take action after a timeout. */
          if (time > (nextPktTime + 2))
          {
            /* Here we 'emulate' a packet RXing in order to prepare for the next action. */
            /* lastHopTime is updated to the time the packet should have been received, which is the current nextPktTime. */
            /* nextPktTime is updated to reflect the next anticipated packet, in 9 or 18ms. */
            /* lastPktTime is untouched, as no real RXing was done. */
            hopchan = (hopchan + 1) % D8_NUM_HOP_CHANNELS;
            frsky_state = (frsky_state + 1) % NUM_FRSKY_STATES;
            frsky_rx_toggle_ant();
            lastHopTime = nextPktTime;
            if (frsky_state == FRSKY_TX_TELEM)
            {
              nextPktTime = nextPktTime + 18;
              rx_state = STATE_PREPARE_TX;
            } else {
              nextPktTime = nextPktTime + 9;
              rx_state = STATE_WILL_RX;
            }
          }
          /* if it has been a long time since the last valid packet, go to a different hop sequence in an attempt to find the tx's hop phase. */
          /* TODO: make this timeout configurable, maybe */
          if (time > (lastPktTime + 1000)) 
            fail_state = STATE_SEARCH;
          break;
          /* end STATE_RUNNING */
          
        case STATE_SEARCH:
          HAL_GPIO_WritePin(LED_RED_GPIO, LED_RED_PIN, LED_RED_STATE_ON);
          if (gotFirstPkt > 1)
            HAL_GPIO_WritePin(LED_GREEN_GPIO, LED_GREEN_PIN, LED_GREEN_STATE_OFF);
          /* hop every 45ms while looking for packets */
          if (time > (lastHopTime + 45))
          {
            hopchan = (hopchan + 1) % D8_NUM_HOP_CHANNELS;
            
            /* TODO: allow TXing while in failsafe. maybe? */
            frsky_state = FRSKY_RX1;
            
            lastHopTime = HAL_GetTick();
            frsky_rx_toggle_ant();
            rx_state = STATE_WILL_RX;
          }
          break;
          /* end STATE_SEARCH */
      }
      break;
      /* end STATE_RXING */
      
    case STATE_RXD:
      /* lastPktTime and lastHopTime are both updated with the current time. */
      /* nextPktTime is updated to reflect the next anticipated packet, in 9 or 18ms. */
      lastPktTime = time;
      lastHopTime = time;
      hopchan = (rxmsg.packet[3] + 1) % D8_NUM_HOP_CHANNELS;
      frsky_state = (rxmsg.packet[3] + 1) % NUM_FRSKY_STATES; // sets up the next state
      fail_state = STATE_RUNNING;
      failsafeStatus = 0;
      HAL_GPIO_WritePin(LED_RED_GPIO, LED_RED_PIN, LED_RED_STATE_OFF);
      HAL_GPIO_WritePin(LED_GREEN_GPIO, LED_GREEN_PIN, LED_GREEN_STATE_ON);
    
      frsky_rx_toggle_ant();
    
      frsky_rx_process_channels();
    
      /* Read and process rssi. Do this after channels! */
      rssi = CC2500_ReadReg(CC2500_REG_RSSI);
//      rssidbm = frsky_getrssidbm(rssi);
      if(rssichan != -1)
      {
        /* turn 0-255 into 988-2012 */
        channelValues[rssichan] = ((uint16_t)rssi * 4) + 988; // TODO: fix ranges
      }
      
      /* read frequency drift estimation and write this value back to the cc2500 offset register. */
      freqoff_est = CC2500_ReadReg(CC2500_REG_FREQEST);
      CC2500_WriteReg(CC2500_REG_FSCTRL0, freqoff_est);
    
      /* nextPktTime is the expected time of the next incoming packet
       * it is either 9ms or 18ms depending on if there is telem txing this cycle. */
      if (frsky_state == FRSKY_TX_TELEM)
      {
        nextPktTime = lastPktTime + 18;
        rx_state = STATE_PREPARE_TX;
      } else {
        nextPktTime = lastPktTime + 9;
        rx_state = STATE_WILL_RX;
      }
      if (gotFirstPkt == 0)
        gotFirstPkt = 1;
      break;
      /* end STATE_RXD */
      
    case STATE_PREPARE_TX:
      frsky2way_d8_build_telem_packet();
      frsky_set_hopchan(hopchan);
      txStartTime = lastHopTime + 2; // set up time to activate txing.
      lastHopTime = lastHopTime + 9; // not actually lasthoptime, but keeps 9ms interval for simplicity.
      rx_state = STATE_WILL_TX;
      break;
      /* end STATE_PREPARE_TX */
    
    case STATE_WILL_TX:
      /* TODO: disable-able telem txing in config. why? cuz. */
      if (time > txStartTime)
      {
        CC2500_WriteTXData(txmsg.packet, txmsg.packet[0]+1);
        rx_state = STATE_TXING;
      }
      break;
      /* end STATE_WILL_TX */
    
    case STATE_TXING:
      if (time > (txStartTime + 8)) // need to give enough time to tx entire packet.
        rx_state = STATE_TXD;
      break;
      /* end STATE_TXING */
      
    case STATE_TXD:
      hopchan = (hopchan + 1) % D8_NUM_HOP_CHANNELS;
      frsky_state = FRSKY_RX1;
      rx_state = STATE_WILL_RX;
      break;
      /* end STATE_TXD */
    
    default:
      rx_state = STATE_SEARCH;
      break;
  }
  /* end rx_state switch statement */
  
  /* stuff to do once after first packet RXd, is there anything? TODO: */
   if (gotFirstPkt == 1)
  {
    gotFirstPkt = 2;
  }
  
  /* detect and handle failsafe condition */
  if ((gotFirstPkt >= 1) & ((time - lastPktTime) > m_config.failsafeDelay) & (failsafeStatus == 0))
  {
    failsafeStatus = 1;
    uint8_t failtype;
    if (m_config.failsafeType == FAILSAFE_AUTODETECT)
    {
      if (m_config.failsafeValues[0] == 0) // failsafe values have not been set.
        failtype = FAILSAFE_STOPOUTPUT;
      else
        failtype = FAILSAFE_SAVEDVALUES;
    } else {
      failtype = m_config.failsafeType;
    }
    
    switch (failtype)
    {
      default:
      case FAILSAFE_STOPOUTPUT:
        output_handle_functions.outputStop();
        break;
      case FAILSAFE_SAVEDVALUES:
        for (uint8_t i = 0; i < MAX_CHANNEL_OUTPUTS; i++)
        {
          channelValues[i] = m_config.failsafeValues[i];
        }
        if(rssichan != -1)
        {
          channelValues[rssichan] = 988; // TODO: fix ranges
        }
        output_handle_functions.outputUpdate();
        break;
    }
  }
  
  /* failsafe button handler */
  /* we have a packet, we're not in failsafe, and we haven't already set failsafes this btnpress. */
  if ((gotFirstPkt >= 1) & (failsafeStatus == 0) & (failsafeBtnSettingStatus == 0))
  {
    if ((HAL_GPIO_ReadPin(BIND_FAIL_BUTTON_GPIO, BIND_FAIL_BUTTON_PIN) == GPIO_PIN_RESET) & (failsafeBtnTime == 0)) // pin is NO and pulled high
    {
      failsafeBtnTime = time;
    }
    else if ((HAL_GPIO_ReadPin(BIND_FAIL_BUTTON_GPIO, BIND_FAIL_BUTTON_PIN) == GPIO_PIN_RESET) & ((time - failsafeBtnTime) > 2000))
    {
      HAL_GPIO_WritePin(LED_RED_GPIO, LED_RED_PIN, LED_RED_STATE_ON);

      failsafeBtnSettingStatus = 1;
      for (uint8_t i = 0; i < MAX_CHANNEL_OUTPUTS; i++)
      {
        m_config.failsafeValues[i] = channelValues[i];
      }
      eeprom_write();
      
      HAL_Delay(1000);
      HAL_GPIO_WritePin(LED_RED_GPIO, LED_RED_PIN, LED_RED_STATE_OFF);
    }
  }
  
  /* Reset failsafe button timer if button is released */
  if (HAL_GPIO_ReadPin(BIND_FAIL_BUTTON_GPIO, BIND_FAIL_BUTTON_PIN) == GPIO_PIN_SET)
  {
    failsafeBtnTime = 0;
    failsafeBtnSettingStatus = 0;
  }
}
Пример #14
0
void CC2500_RfSettings(void)
{
	
#if 1
		CC2500_WriteReg(CCxxx0_FSCTRL1,	0x09);	// 0x0c
		CC2500_WriteReg(CCxxx0_FSCTRL0,	0x00);
		CC2500_WriteReg(CCxxx0_FREQ2,	0x5D);
		CC2500_WriteReg(CCxxx0_FREQ1,	0x93);
		CC2500_WriteReg(CCxxx0_FREQ0,	0xB1);
#ifdef _10k
		CC2500_WriteReg(CCxxx0_MDMCFG4,	0x78); //0x78-10k   0x86
		CC2500_WriteReg(CCxxx0_MDMCFG3,	0x93); //0x93-10k   0x83
//		CC2500_WriteReg(CCxxx0_MDMCFG2,	0x70);
		CC2500_WriteReg(CCxxx0_MDMCFG2,	0x03); //0x03-10k  0x03
		CC2500_WriteReg(CCxxx0_MDMCFG1,	0x22); //0x22-10k
		CC2500_WriteReg(CCxxx0_MDMCFG0,	0xF8); //0xf8        0xf8		

#else
		CC2500_WriteReg(CCxxx0_MDMCFG4,	0x2D); //0x78-10k   0x86
		CC2500_WriteReg(CCxxx0_MDMCFG3,	0x3B); //0x93-10k   0x83
//		CC2500_WriteReg(CCxxx0_MDMCFG2,	0x70);
		CC2500_WriteReg(CCxxx0_MDMCFG2,	0x73); //0x03-10k  0x03
		CC2500_WriteReg(CCxxx0_MDMCFG1,	0xA2); //0x22-100  0x22
		CC2500_WriteReg(CCxxx0_MDMCFG0,	0xF8); //0xf8        0xf8
#endif

		CC2500_WriteReg(CCxxx0_CHANNR,	0x00);
		CC2500_WriteReg(CCxxx0_DEVIATN,	0x01);	//0x44
		CC2500_WriteReg(CCxxx0_FREND1,	0x56);	//0xB6   56错误机率减少
		CC2500_WriteReg(CCxxx0_FREND0,	0x10);
		CC2500_WriteReg(CCxxx0_MCSM1,	0x00);  // 0X00>NO CCA; 0X30>CCA   ?????
		CC2500_WriteReg(CCxxx0_MCSM0,	0x18);
		CC2500_WriteReg(CCxxx0_FOCCFG,	0x15);	// 0x1D   频率偏移补偿
		CC2500_WriteReg(CCxxx0_BSCFG,	0x6C);	// 0x1c   位同步配置
		CC2500_WriteReg(CCxxx0_AGCCTRL2,	0x07);	// 0xc3    增益控制
		CC2500_WriteReg(CCxxx0_AGCCTRL1,	0x00);	// cca=0x10
		CC2500_WriteReg(CCxxx0_AGCCTRL0,	0x91);	// 0xb2
		CC2500_WriteReg(CCxxx0_FSCAL3,	0xEA);
		CC2500_WriteReg(CCxxx0_FSCAL2,	0x0A);  //0x0a - 250k  0x06 --10k,0x08-2.4k
		CC2500_WriteReg(CCxxx0_FSCAL1,	0x00);	// 增加频率同步校准

		CC2500_WriteReg(CCxxx0_FSCAL0,	0x11);
		CC2500_WriteReg(CCxxx0_FSTEST,	0x59);
		CC2500_WriteReg(CCxxx0_TEST2,	0x8F);  // 0x88
		CC2500_WriteReg(CCxxx0_TEST1,	0x21);	// 0x31
		CC2500_WriteReg(CCxxx0_TEST0,	0x0B);
		CC2500_WriteReg(CCxxx0_IOCFG2,	0x06);	//29// CCA=0x09:1=free   ??????
		CC2500_WriteReg(CCxxx0_IOCFG0,	0x06);	//                  ?????
		CC2500_WriteReg(CCxxx0_PKTCTRL1,	0x00);	//无地址检查		//                      ??????
		CC2500_WriteReg(CCxxx0_PKTCTRL0,	0x04);	//0x41 whiter+val
		CC2500_WriteReg(CCxxx0_ADDR,		0x00);
		CC2500_WriteReg(CCxxx0_PKTLEN,	PACKET_LEN);//                      ??????
      		// CC2500_ReadReg(CCxxx0_MDMCFG1);
#else
	CC2500_WriteReg(CCxxx0_IOCFG2,0x0B);//0x0B,   // IOCFG2    GDO2 output pin configuration.
	CC2500_WriteReg(CCxxx0_IOCFG1,0x06);   //IOCFG1
	CC2500_WriteReg(CCxxx0_IOCFG0,0x06);  // IOCFG0   GDO0 output pin configuration. 
	CC2500_WriteReg(CCxxx0_FIFOTHR,0x07);   //FIFOTHR
	CC2500_WriteReg(CCxxx0_SYNC1,0xD3);	//SYNC1 MSB
	CC2500_WriteReg(CCxxx0_SYNC0,0x91);     //SYNC0 LSB
	CC2500_WriteReg(CCxxx0_PKTLEN,64);   // PKTLEN    Packet length.
	CC2500_WriteReg(CCxxx0_PKTCTRL1,0x02);   // PKTCTRL1  Packet automation control.
	CC2500_WriteReg(CCxxx0_PKTCTRL0,0x05);  // PKTCTRL0  Packet automation control.
	CC2500_WriteReg(CCxxx0_ADDR,0x01);  // ADDR      Device address.
	
	CC2500_WriteReg(CCxxx0_CHANNR,0x00);  // CHANNR    Channel number.
	CC2500_WriteReg(CCxxx0_FSCTRL1,0x07);  // FSCTRL1   Frequency synthesizer control.
	CC2500_WriteReg(CCxxx0_FSCTRL0,0x00);  // FSCTRL0   Frequency synthesizer control.
	CC2500_WriteReg(CCxxx0_FREQ2,0x5D);  // FREQ2     Frequency control word, high u8.
	CC2500_WriteReg(CCxxx0_FREQ1,0x93);  // FREQ1     Frequency control word, middle u8.
	CC2500_WriteReg(CCxxx0_FREQ0,0xB1);  // FREQ0     Frequency control word, low u8.
	CC2500_WriteReg(CCxxx0_MDMCFG4,0x2D);  // MDMCFG4   Modem configuration.
	CC2500_WriteReg(CCxxx0_MDMCFG3,0x3B);  // MDMCFG3   Modem configuration.
	CC2500_WriteReg(CCxxx0_MDMCFG2,0x73);  // MDMCFG2   Modem configuration.
	CC2500_WriteReg(CCxxx0_MDMCFG1,0x22);  // MDMCFG1   Modem configuration.

	CC2500_WriteReg(CCxxx0_MDMCFG0,0xF8);  // MDMCFG0   Modem configuration.
	CC2500_WriteReg(CCxxx0_DEVIATN,0x47);  // DEVIATN   Modem deviation setting (when FSK modulation is enabled).
	CC2500_WriteReg(CCxxx0_MCSM2,0x00);   // MCSM2     Main Radio Control State Machine configuration.
	CC2500_WriteReg(CCxxx0_MCSM1,0x02);   // MCSM1     Main Radio Control State Machine configuration.
	CC2500_WriteReg(CCxxx0_MCSM0,0x18);   // MCSM0     Main Radio Control State Machine configuration.
	CC2500_WriteReg(CCxxx0_FOCCFG,0x1D);  // FOCCFG    Frequency Offset Compensation Configuration.
	CC2500_WriteReg(CCxxx0_BSCFG,0x1C);  // BSCFG     Bit synchronization Configuration.
	CC2500_WriteReg(CCxxx0_AGCCTRL2,0xC7);  // AGCCTRL2  AGC control.
	CC2500_WriteReg(CCxxx0_AGCCTRL1,0x00);  // AGCCTRL1  AGC control.
	CC2500_WriteReg(CCxxx0_AGCCTRL0,0xB2);  // AGCCTRL0  AGC control.

	CC2500_WriteReg(CCxxx0_WOREVT1,0x00);  // WOREVT1
    CC2500_WriteReg(CCxxx0_WOREVT0,0x00);  // WOREVT0
    CC2500_WriteReg(CCxxx0_WORCTRL,0x00);  // WORCTRL
    CC2500_WriteReg(CCxxx0_FREND1,0xB6);  // FREND1    Front end RX configuration.
	CC2500_WriteReg(CCxxx0_FREND0,0x10);  // FREND0    Front end RX configuration.
	CC2500_WriteReg(CCxxx0_FSCAL3,0xEA);  // FSCAL3    Frequency synthesizer calibration.
	CC2500_WriteReg(CCxxx0_FSCAL2,0x0A);  // FSCAL2    Frequency synthesizer calibration.
	CC2500_WriteReg(CCxxx0_FSCAL1,0x00);  // FSCAL1    Frequency synthesizer calibration.
	CC2500_WriteReg(CCxxx0_FSCAL0,0x11);  // FSCAL0    Frequency synthesizer calibration.
	CC2500_WriteReg(CCxxx0_RCCTRL1,0x00);   //RCCTRL1

	CC2500_WriteReg(CCxxx0_RCCTRL0,0x00);   //RCCTRL0
	CC2500_WriteReg(CCxxx0_FSTEST,0x59);  // FSTEST    Frequency synthesizer calibration.
	CC2500_WriteReg(CCxxx0_PTEST,0x00);   //PTEST
	//CC2500_WriteReg(CCxxx0_AGCTEST,0x00);  //AGCTEST
	//CC2500_WriteReg(CCxxx0_TEST2,0x88);  // TEST2     Various test settings.
	//CC2500_WriteReg(CCxxx0_TEST1,0x31);  // TEST1     Various test settings.
	//CC2500_WriteReg(CCxxx0_TEST0,0x0B);  // TEST0     Various test settings.
#endif

	//for(i=0;i<=CCxxx0_TEST0;i++)
		//Debug("0x%x:0x%x\n\r",i,CC2500_ReadReg(i));
}