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 ); } }
/* 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; }
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(); } }
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); }
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 }