static uint16_t tx_delay(void) { if (delay_count==0) { // if first try, quick timerB_set_alarm_from_now(ALARM_RETRY, 2, 0); timerB_register_cb(ALARM_RETRY, tx_try); } else if (delay_count >= DELAY_COUNT_MAX) { // to many tries, abort // delete packet txframe.length = 0; // reset callback cc1101_gdo0_register_callback(rx_parse); // reset rx cc1101_cmd_idle(); rx_set(); PRINTF("too many tries\n"); // call the error callback if (error_cb) { return error_cb(); } } else { uint16_t delay; // delay randomly between 1ms and 63ms delay = rand(); delay &= ((1<<11)-1); delay += 32; timerB_set_alarm_from_now(ALARM_RETRY, delay, 0); timerB_register_cb(ALARM_RETRY, tx_try); } delay_count ++; return 0; }
static void vADCInit(void) { uint16_t period; // Configure GPIO1 (P2.3) as output and high, as a voltage reference P2SEL &= ~BV(3); P2DIR |= BV(3); P2OUT |= BV(3); // Reset frame data_frame.length = 0; data_frame.seq = 0; // Start the timer period = MS_TO_TICKS(10); timerB_set_alarm_from_now(TIMERB_ALARM_CCR6, period, period); timerB_register_cb(TIMERB_ALARM_CCR6, measure_time); /* Configure ADC pins for analog input */ P6SEL |= BV(0) | BV(1) | BV(3) | BV(4) | BV(6) | BV(7); P6DIR &= ~(BV(0) | BV(1) | BV(3) | BV(4) | BV(6) | BV(7)); /* 38us sampling, internal reference 1.5V */ ADC12CTL0 = SHT0_7 | MSC | REFON | REF2_5V | ADC12ON; /* Start@ADD0, ADC12SC bit source, seq. of chan. */ ADC12CTL1 = SHP | CONSEQ_1; /* Channel A0, vREF */ ADC12MCTL0 = INCH_0 | SREF_1; /* Channel A1, vREF */ ADC12MCTL1 = INCH_1 | SREF_1; /* Channel A4, vREF */ ADC12MCTL2 = INCH_4 | SREF_1; /* Channel A3, vREF */ ADC12MCTL3 = INCH_3 | SREF_1; /* Channel A6, vREF */ ADC12MCTL4 = INCH_6 | SREF_1; /* Channel A7, vREF, End Of Sequence */ ADC12MCTL5 = EOS | INCH_7 | SREF_1; /* Interrupt on end of sequence */ ADC12IE = BV(5); /* Start ADC conversions */ ADC12CTL0 |= ENC; }
static uint16_t tx_done(void) { // if destination is broadcast, don't wait for ACK if ((txframe.dst_addr[0]==0xFF) && (txframe.dst_addr[1]==0xFF)) { cc1101_gdo0_register_callback(rx_parse); txframe.length = 0; rx_set(); if (sent_cb) { return sent_cb(); } } else { cc1101_gdo0_register_callback(tx_ack); timerB_set_alarm_from_now(ALARM_RETRY, ACK_TIMEOUT, 0); timerB_register_cb(ALARM_RETRY, tx_delay); } return 0; }
uint16_t next_send(void) { counter++; if (counter >= MAX_COUNTER) { state = SM_LOOP_TX; counter = 0; return 1; } else { timerB_set_alarm_from_now(TIMERB_ALARM_CCR5, SEND_DATA_PERIOD, 0); timerB_register_cb(TIMERB_ALARM_CCR5, next_send); return 0; } return 0; }
int main(void) { WDTCTL = WDTPW+WDTHOLD; set_mcu_speed_xt2_mclk_8MHz_smclk_1MHz(); set_aclk_div(1); LEDS_INIT(); LEDS_OFF(); ds2411_init(); nodeaddr = (((uint16_t)ds2411_id.serial1)<<8) + (ds2411_id.serial0); uart0_init(UART0_CONFIG_1MHZ_115200); uart0_register_callback(char_rx); eint(); printf("[APP];BOOTING;%.4x\n",nodeaddr); //check if this node is the sink if (nodeaddr == sink_nodes) { type = SINK; level = DEFAULT_LEVEL; } else { //retrieve father for (idx=0; idx<NUMBER_NODES; idx++) { if (list_nodes[idx] == nodeaddr) { if(father_nodes1[idx] != 0x0000) { parent_id = father_nodes1[idx]; level = 12; break; } } } } //hack for mobile /*if(nodeaddr == 0x1f5d) { parent_id = 0x0000; mac_set_mobile(1); level = 12; }*/ mac_init(10); mac_set_rx_cb(packet_received); mac_set_error_cb(packet_error); mac_set_sent_cb(packet_sent); timerB_set_alarm_from_now(TIMERB_ALARM_CCR6, 32768, 32768); timerB_register_cb(TIMERB_ALARM_CCR6, inc_clock); while (1) { LPM1; if (state == SM_TX) { if (level != UNDEF_LEVEL && type != SINK) { seq_max = NUM_SEQ_MAX; delay = rand(); delay &= 0xCFFF; delay += 12000; //(369ms < delay < 1991ms) timerB_set_alarm_from_now(TIMERB_ALARM_CCR5, delay, 0); timerB_register_cb(TIMERB_ALARM_CCR5, next_send); } else { printf("[APP];NOROUTE\n"); } state = SM_IDLE; } else if (state == SM_LOOP_TX) { if (level != UNDEF_LEVEL) { sprintf(sourceaddr,"%.4x",nodeaddr); data_txframe[0] = DATA; data_txframe[1] = level-1; data_txframe[2] = sourceaddr[0]; data_txframe[3] = sourceaddr[1]; data_txframe[4] = sourceaddr[2]; data_txframe[5] = sourceaddr[3]; data_txframe[6] = seq; //sequence data_txframe[7] = 1; //hops txlength = 8; stat_add(STAT_APP_TX); printf("[APP];NODE_TX;%.4x;%.4x;%u;%u-%u\n", nodeaddr, parent_id, seq, global_clock, timerB_time()/32); seq++; mac_send(data_txframe, txlength, parent_id); if (DEBUG_LEDS == 1) { LED_GREEN_ON(); } if (seq < seq_max) { timerB_set_alarm_from_now(TIMERB_ALARM_CCR5, SEND_DATA_PERIOD, 0); timerB_register_cb(TIMERB_ALARM_CCR5, next_send); } } state = SM_IDLE; } } return 0; }
void mac_init(uint8_t channel) { int16_t i; // initialize the unique serial number chip and set node address accordingly ds2411_init(); node_addr = ds2411_id.serial0 & HEADER_ADDR_MASK; // seed the random number generator srand((ds2411_id.serial0<<8)+ds2411_id.serial1); // initialize the timerB, with the beacon perdiod timerB_init(); timerB_start_ACLK_div(TIMERB_DIV_1); timerB_set_alarm_from_now(ALARM_SLOTS, SLOT_LENGTH, SLOT_LENGTH); timerB_register_cb(ALARM_SLOTS, slot_alarm); // configure the radio cc1101_init(); cc1101_cmd_idle(); /* configure the radio behaviour */ cc1101_cfg_append_status(CC1101_APPEND_STATUS_ENABLE); cc1101_cfg_crc_autoflush(CC1101_CRC_AUTOFLUSH_DISABLE); cc1101_cfg_white_data(CC1101_DATA_WHITENING_ENABLE); cc1101_cfg_crc_en(CC1101_CRC_CALCULATION_ENABLE); cc1101_cfg_freq_if(0x0E); cc1101_cfg_fs_autocal(CC1101_AUTOCAL_NEVER); cc1101_cfg_mod_format(CC1101_MODULATION_MSK); cc1101_cfg_sync_mode(CC1101_SYNCMODE_30_32); cc1101_cfg_manchester_en(CC1101_MANCHESTER_DISABLE); cc1101_cfg_cca_mode(CC1101_CCA_MODE_RSSI_PKT_RX); // freq = 860MHz cc1101_write_reg(CC1101_REG_FREQ2, 0x1F); cc1101_write_reg(CC1101_REG_FREQ1, 0xDA); cc1101_write_reg(CC1101_REG_FREQ0, 0x12); // configure the radio channel (300kHz spacing) cc1101_cfg_chanspc_e(0x3); cc1101_cfg_chanspc_m(0x6C); cc1101_cfg_chan(channel<<1); // channel x2 to get 600kHz spacing // set channel bandwidth (560 kHz) cc1101_cfg_chanbw_e(0); cc1101_cfg_chanbw_m(2); // set data rate (0xD/0x2F is 250kbps) cc1101_cfg_drate_e(0x0D); cc1101_cfg_drate_m(0x2F); // go to RX after TX cc1101_cfg_rxoff_mode(CC1101_RXOFF_MODE_STAY_RX); cc1101_cfg_txoff_mode(CC1101_TXOFF_MODE_RX); uint8_t table[] = {CC1101_868MHz_TX_0dBm}; cc1101_cfg_patable(table, 1); cc1101_cfg_pa_power(0); // set IDLE state, flush everything cc1101_cmd_idle(); cc1101_cmd_flush_rx(); cc1101_cmd_flush_tx(); // configure irq cc1101_cfg_gdo0(CC1101_GDOx_SYNC_WORD); cc1101_gdo0_int_set_falling_edge(); // configure the beacon frame beacon_msg.hdr.length = BEACON_LENGTH-1; HEADER_SET_ADDR(beacon_msg.hdr, node_addr); HEADER_SET_TYPE(beacon_msg.hdr,BEACON_TYPE); beacon_msg.seq=0; // initialize the slot management service tdma_mgt_init(); // reset slot count slot_count = -1; // init the data slots for (i=0;i<DATA_SLOT_MAX;i++) { mac_slots[i].ready=0; mac_slots[i].addr=0; } // reset the callback new_data_cb = 0x0; }