Пример #1
0
void
rf_moritz_task(void)
{
  uint8_t enc[MAX_MORITZ_MSG];
  uint8_t rssi;

  if(!moritz_on)
    return;

  // see if a CRC OK pkt has been arrived
  if(bit_is_set( CC1100_IN_PORT, CC1100_IN_PIN )) {
    //errata #1 does not affect us, because we wait until packet is completely received
    enc[0] = CC1100_READREG( CC1100_RXFIFO ) & 0x7f; // read len

    if (enc[0]>=MAX_MORITZ_MSG)
         enc[0] = MAX_MORITZ_MSG-1;

    CC1100_ASSERT;
    cc1100_sendbyte( CC1100_READ_BURST | CC1100_RXFIFO );

    for (uint8_t i=0; i<enc[0]; i++) {
         enc[i+1] = cc1100_sendbyte( 0 );
    }

    // RSSI is appended to RXFIFO
    rssi = cc1100_sendbyte( 0 );
    // And Link quality indicator, too
    /* LQI = */ cc1100_sendbyte( 0 );

    CC1100_DEASSERT;

    moritz_handleAutoAck(enc);

    if (tx_report & REP_BINTIME) {

      DC('z');
      for (uint8_t i=0; i<=enc[0]; i++)
      DC( enc[i] );
    } else {
      DC('Z');
      for (uint8_t i=0; i<=enc[0]; i++)
        DH2( enc[i] );
      if (tx_report & REP_RSSI)
        DH2(rssi);
      DNL();
    }

    return;
  }

  if(CC1100_READREG( CC1100_MARCSTATE ) == 17) {
    CCSTROBE( CC1100_SFRX  );
    CCSTROBE( CC1100_SIDLE );
    CCSTROBE( CC1100_SRX   );
  }
}
Пример #2
0
/* longPreamble is necessary for unsolicited messages to wakeup the receiver */
void
moritz_sendraw(uint8_t *dec, int longPreamble)
{
  uint8_t hblen = dec[0]+1;
  //1kb/s = 1 bit/ms. we send 1 sec preamble + hblen*8 bits
  uint32_t sum = (longPreamble ? 100 : 0) + (hblen*8)/10;
  if (credit_10ms < sum) {
    DS_P(PSTR("LOVF\r\n"));
    return;
  }
  credit_10ms -= sum;

  // in Moritz mode already?
  if(!moritz_on) {
    rf_moritz_init();
  }

  if(CC1100_READREG( CC1100_MARCSTATE ) != MARCSTATE_RX) { //error
    DC('Z');
    DC('E');
    DC('R');
    DC('R');
    DC('1');
    DH2(CC1100_READREG( CC1100_MARCSTATE ));
    DNL();
    rf_moritz_init();
    return;
  }

  /* We have to keep at least 20 ms of silence between two sends
   * (found out by trial and error). ticks runs at 125 Hz (8 ms per tick),
   * so we wait for 3 ticks.
   * This looks a bit cumbersome but handles overflows of ticks gracefully.
   */
  if(lastSendingTicks)
    while(ticks == lastSendingTicks || ticks == lastSendingTicks+1)
      my_delay_ms(1);

  /* Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1 (this is the case) (takes 809μs)
   * start sending - CC1101 will send preamble continuously until TXFIFO is filled.
   * The preamble will wake up devices. See http://e2e.ti.com/support/low_power_rf/f/156/t/142864.aspx
   * It will not go into TX mode instantly if channel is not clear (see CCA_MODE), thus ccTX tries multiple times */
#ifdef CC_ID
  do {
    CCSTROBE(CC1100_STX);
  } while (CC1100_READREG(CC1100_MARCSTATE) != MARCSTATE_TX);
#else
  ccTX();
#endif
  if(CC1100_READREG( CC1100_MARCSTATE ) != MARCSTATE_TX) { //error
    DC('Z');
    DC('E');
    DC('R');
    DC('R');
    DC('2');
    DH2(CC1100_READREG( CC1100_MARCSTATE ));
    DNL();
    rf_moritz_init();
    return;
  }

  if(longPreamble) {
    /* Send preamble for 1 sec. Keep in mind that waiting for too long may trigger the watchdog (2 seconds on CUL) */
    for(int i=0;i<10;++i)
      my_delay_ms(100); //arg is uint_8, so loop
  }

  // send
  CC1100_ASSERT;
  cc1100_sendbyte(CC1100_WRITE_BURST | CC1100_TXFIFO);

  for(uint8_t i = 0; i < hblen; i++) {
    cc1100_sendbyte(dec[i]);
  }

  CC1100_DEASSERT;

  //Wait for sending to finish (CC1101 will go to RX state automatically
  //after sending
  uint8_t i;
  for(i=0; i< 200;++i) {
    if( CC1100_READREG( CC1100_MARCSTATE ) == MARCSTATE_RX)
      break; //now in RX, good
    if( CC1100_READREG( CC1100_MARCSTATE ) != MARCSTATE_TX)
      break; //neither in RX nor TX, probably some error
    my_delay_ms(1);
  }

  if(CC1100_READREG( CC1100_MARCSTATE ) != MARCSTATE_RX) { //error
    DC('Z');
    DC('E');
    DC('R');
    DC('R');
    DC('3');
    DH2(CC1100_READREG( CC1100_MARCSTATE ));
    DNL();
    rf_moritz_init();
  }

  if(!moritz_on) {
    set_txrestore();
  }
  lastSendingTicks = ticks;
}
Пример #3
0
void
asksin_send(char *in)
{
  uint8_t msg[MAX_ASKSIN_MSG];
  uint8_t ctl;
  uint8_t l;
  uint32_t ts1, ts2;

  uint8_t hblen = fromhex(in+1, msg, MAX_ASKSIN_MSG-1);

  if ((hblen-1) != msg[0]) {
//  DS_P(PSTR("LENERR\r\n"));
    return;
  }

  // in AskSin mode already?
  if(!asksin_on) {
    rf_asksin_init();
    my_delay_ms(3);             // 3ms: Found by trial and error
  }

  ctl = msg[2];

  // "crypt"
  msg[1] = (~msg[1]) ^ 0x89;

  for (l = 2; l < msg[0]; l++)
    msg[l] = (msg[l-1] + 0xdc) ^ msg[l];
  
  msg[l] = msg[l] ^ ctl;

  // enable TX, wait for CCA
  get_timestamp(&ts1);
  do {
    CCSTROBE(CC1100_STX);
    if (CC1100_READREG(CC1100_MARCSTATE) != MARCSTATE_TX) {
      get_timestamp(&ts2);
      if (((ts2 > ts1) && (ts2 - ts1 > ASKSIN_WAIT_TICKS_CCA)) ||
          ((ts2 < ts1) && (ts1 + ASKSIN_WAIT_TICKS_CCA < ts2))) {
        DS_P(PSTR("ERR:CCA\r\n"));
        goto out;
      }
    }
  } while (CC1100_READREG(CC1100_MARCSTATE) != MARCSTATE_TX);

  if (ctl & (1 << 4)) { // BURST-bit set?
    // According to ELV, devices get activated every 300ms, so send burst for 360ms
    for(l = 0; l < 3; l++)
      my_delay_ms(120); // arg is uint_8, so loop
  } else {
  	my_delay_ms(10);
  }

  // send
  CC1100_ASSERT;
  cc1100_sendbyte(CC1100_WRITE_BURST | CC1100_TXFIFO);

  for(uint8_t i = 0; i < hblen; i++) {
    cc1100_sendbyte(msg[i]);
  }

  CC1100_DEASSERT;

  // wait for TX to finish
  while(CC1100_READREG( CC1100_MARCSTATE ) == MARCSTATE_TX)
    ;

out:
  if (CC1100_READREG( CC1100_MARCSTATE ) == MARCSTATE_TXFIFO_UNDERFLOW) {
      CCSTROBE( CC1100_SFTX  );
      CCSTROBE( CC1100_SIDLE );
      CCSTROBE( CC1100_SNOP  );
  }
  
  if(asksin_on) {
    do {
      CCSTROBE(CC1100_SRX);
    } while (CC1100_READREG(CC1100_MARCSTATE) != MARCSTATE_RX);
  } else {
    set_txrestore();
  }
}
Пример #4
0
void
rf_asksin_init(void)
{

#ifdef ARM
#ifndef CC_ID
  AT91C_BASE_AIC->AIC_IDCR = 1 << CC1100_IN_PIO_ID;	// disable INT - we'll poll...
#endif

  CC1100_CS_BASE->PIO_PPUER = _BV(CC1100_CS_PIN); 		//Enable pullup
  CC1100_CS_BASE->PIO_OER = _BV(CC1100_CS_PIN);			//Enable output
  CC1100_CS_BASE->PIO_PER = _BV(CC1100_CS_PIN);			//Enable PIO control

#else
  EIMSK &= ~_BV(CC1100_INT);                 // disable INT - we'll poll...
  SET_BIT( CC1100_CS_DDR, CC1100_CS_PIN );   // CS as output
#endif

  CC1100_DEASSERT;                           // Toggle chip select signal
  my_delay_us(30);
  CC1100_ASSERT;
  my_delay_us(30);
  CC1100_DEASSERT;
  my_delay_us(45);

  CCSTROBE( CC1100_SRES );                   // Send SRES command
  my_delay_us(100);

#ifdef CC_ID
  CC1100_ASSERT;
  uint8_t *cfg = EE_CC1100_CFG;
  for(uint8_t i = 0; i < EE_CC1100_CFG_SIZE; i++) {
      cc1100_sendbyte(erb(cfg++));
  }
  CC1100_DEASSERT;

  uint8_t *pa = EE_CC1100_PA;
    CC1100_ASSERT;                             // setup PA table
    cc1100_sendbyte( CC1100_PATABLE | CC1100_WRITE_BURST );
    for (uint8_t i = 0;i<8;i++) {
      cc1100_sendbyte(erb(pa++));
    }
    CC1100_DEASSERT;
#endif
  // load configuration
  for (uint8_t i = 0; i < sizeof(ASKSIN_CFG); i += 2) {
    CC1100_WRITEREG( pgm_read_byte(&ASKSIN_CFG[i]),
                     pgm_read_byte(&ASKSIN_CFG[i+1]) );
  }

#ifdef HAS_ASKSIN_FUP
  if (asksin_update_mode) {
    for (uint8_t i = 0; i < sizeof(ASKSIN_UPDATE_CFG); i += 2) {
      cc1100_writeReg( pgm_read_byte(&ASKSIN_UPDATE_CFG[i]),
                       pgm_read_byte(&ASKSIN_UPDATE_CFG[i+1]) );
    }
  }
#endif
  
  CCSTROBE( CC1100_SCAL );

  my_delay_ms(4);

  // enable RX, but don't enable the interrupt
  do {
    CCSTROBE(CC1100_SRX);
  } while (CC1100_READREG(CC1100_MARCSTATE) != MARCSTATE_RX);
}
Пример #5
0
void
rf_asksin_task(void)
{
  uint8_t msg[MAX_ASKSIN_MSG];
  uint8_t this_enc, last_enc;
  uint8_t rssi;
  uint8_t l;

  if(!asksin_on)
    return;

  // see if a CRC OK pkt has been arrived
  if (bit_is_set( CC1100_IN_PORT, CC1100_IN_PIN )) {
    msg[0] = CC1100_READREG( CC1100_RXFIFO ) & 0x7f; // read len

    if (msg[0] >= MAX_ASKSIN_MSG) {
      // Something went horribly wrong, out of sync?
      rf_asksin_reset_rx();
      return;
    }

    CC1100_ASSERT;
    cc1100_sendbyte( CC1100_READ_BURST | CC1100_RXFIFO );
    
    for (uint8_t i=0; i<msg[0]; i++) {
         msg[i+1] = cc1100_sendbyte( 0 );
    }
    
    rssi = cc1100_sendbyte( 0 );
    /* LQI = */ cc1100_sendbyte( 0 );

    CC1100_DEASSERT;

    do {
      CCSTROBE(CC1100_SRX);
    } while (CC1100_READREG(CC1100_MARCSTATE) != MARCSTATE_RX);

    last_enc = msg[1];
    msg[1] = (~msg[1]) ^ 0x89;
    
    for (l = 2; l < msg[0]; l++) {
         this_enc = msg[l];
         msg[l] = (last_enc + 0xdc) ^ msg[l];
         last_enc = this_enc;
    }
    
    msg[l] = msg[l] ^ msg[2];
    
    if (tx_report & REP_BINTIME) {
      
      DC('a');
      for (uint8_t i=0; i<=msg[0]; i++)
      DC( msg[i] );
         
    } else {
      DC('A');
      
      for (uint8_t i=0; i<=msg[0]; i++)
        DH2( msg[i] );
      
      if (tx_report & REP_RSSI)
        DH2(rssi);
      
      DNL();
    }
  }

  switch(CC1100_READREG( CC1100_MARCSTATE )) {
    case MARCSTATE_RXFIFO_OVERFLOW:
      CCSTROBE( CC1100_SFRX  );
    case MARCSTATE_IDLE:
      CCSTROBE( CC1100_SIDLE );
      CCSTROBE( CC1100_SNOP  );
      CCSTROBE( CC1100_SRX   );
      break;
  }

#ifdef HAS_CC1101_RX_PLL_LOCK_CHECK_TASK_WAIT
  CC1101_RX_CHECK_PLL_WAIT_TASK();
#endif
}