Esempio n. 1
0
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;
}
Esempio n. 2
0
static uint16_t tx_ack(void) {
    uint8_t status[2];
    uint16_t dst;
    uint16_t ret_val;

    /* Check if there are bytes in FIFO */
    if (cc1101_status_rxbytes() == 0) {
        return rx_set();
    }

    /* Check Length is correct */
    cc1101_fifo_get( (uint8_t*) &(ack.length), 1);

    // if too big, flush
    if ( ack.length != HEADER_LENGTH ) {
        return rx_set();
    }

    /* Get Data */
    cc1101_fifo_get( (uint8_t*) &(ack.length)+1, ack.length);

    /* Get Status Bytes */
    cc1101_fifo_get(status, 2);

    /* Check CRC */
    if ( (status[1] & 0x80) == 0 ) {
        return rx_set();
    }

    ret_val = 0;

    /* Compute addresses */
    dst = (((uint16_t)ack.dst_addr[0])<<8) + ack.dst_addr[1];

    /* Check addresses */
    if ( (dst==node_addr) && (ack.src_addr[0]==txframe.dst_addr[0]) \
                           && (ack.src_addr[1]==txframe.dst_addr[1]) ) {
        txframe.length = 0;
        timerB_unset_alarm(ALARM_RETRY);
        cc1101_gdo0_register_callback(rx_parse);
        rx_set();
        if (sent_cb) {
            return sent_cb();
        }
    }
    return rx_set();
}
Esempio n. 3
0
static uint16_t tx_try(void) {
    uint8_t status;

    if (txframe.length == 0) {
        PRINTF("tx_try no packet error\n");
        return rx_set();
    }

    // if radio not in RX, delay
    status = cc1101_status() & 0x70;
    if ( status != 0x10) {
        PRINTF("try sending radio state error (%x)\n", status);
        tx_delay();

        return rx_set();
    }

    // if there are some weird bytes in TX FIFO, flush everything
    if (cc1101_status_txbytes()!=0) {
        PRINTF("mac had to flush\n");
        cc1101_cmd_idle();
        cc1101_cmd_flush_tx();
        cc1101_cmd_flush_rx();
    }

    // try to send
    cc1101_cmd_tx();

    // get chip status
    status = cc1101_status() & 0x70;

    // if status is not RX
    if ( status != 0x10) {
        // put data in fifo
        cc1101_fifo_put((uint8_t*)&txframe, txframe.length+1);
        cc1101_gdo0_register_callback(tx_done);
    } else {
        tx_delay();
        rx_set();
    }

    return 0;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
static uint16_t rx_ackdone(void) {
    cc1101_gdo0_register_callback(rx_parse);
    return rx_set();
}
Esempio n. 6
0
static uint16_t rx_parse(void) {
    uint8_t status[2];
    uint16_t src, dst;
    uint16_t ret_val;
    int16_t rssi;

    /* Check if there are bytes in FIFO */
    if ( (cc1101_status_rxbytes() == 0) || (cc1101_status_rxbytes() > 64) ) {
        return rx_set();
    }

    /* Check Length is correct */
    cc1101_fifo_get( (uint8_t*) &(rxframe.length), 1);
    // if too big, flush
    if ( rxframe.length > sizeof(rxframe)-1 ) {
        return rx_set();
    }

    /* Get Data */
    cc1101_fifo_get( (uint8_t*) &(rxframe.length)+1, rxframe.length);

    /* Get Status Bytes */
    cc1101_fifo_get(status, 2);

    /* Check CRC */
    if ( (status[1] & 0x80) == 0 ) {
        return rx_set();
    }

    /* Check for min length */
    if ( rxframe.length < HEADER_LENGTH ) {
        return rx_set();
    }

    /* Compute addresses */
    dst = (((uint16_t)rxframe.dst_addr[0])<<8) + rxframe.dst_addr[1];
    src = (((uint16_t)rxframe.src_addr[0])<<8) + rxframe.src_addr[1];

    ret_val = 0;

    int len;
    len = rxframe.length;
    len -= HEADER_LENGTH;

    rssi = status[0] >= 128 ? status[0]-256 : status[0];
    rssi -= 140;

    // if for me, send an ACK
    if (dst==node_addr) {
        ack.length = HEADER_LENGTH;
        ack.type = TYPE_ACK;
        ack.dst_addr[0] = rxframe.src_addr[0];
        ack.dst_addr[1] = rxframe.src_addr[1];
        ack.src_addr[0] = rxframe.dst_addr[0];
        ack.src_addr[1] = rxframe.dst_addr[1];
        if (cc1101_status_txbytes()) {
            cc1101_cmd_flush_tx();
        }
        cc1101_cmd_tx();
        cc1101_fifo_put((uint8_t*)&ack, ack.length+1);
        cc1101_gdo0_register_callback(rx_ackdone);

        if (received_cb) {
            return received_cb(rxframe.payload, len, src, rssi);
        }

    } else if ( (dst==0xFFFF) && received_cb ) {
        /* Call the packet received function */
        ret_val = received_cb(rxframe.payload, len, src, rssi);
        ret_val |= rx_set();
        return ret_val;
    } else {
        return rx_set();
    }

    return 0;
}
Esempio n. 7
0
critical void mac_restart(void) {
    rx_set();
}
Esempio n. 8
0
void mac_init(uint8_t channel)
{
    // initialize the unique serial number chip and set node address accordingly
    ds2411_init();
    node_addr = (((uint16_t)ds2411_id.serial1)<<8) + (ds2411_id.serial0);

    // seed the random number generator
    srand(node_addr);

    // reset callbacks
    received_cb = 0x0;
    sent_cb = 0x0;
    error_cb = 0x0;

    // initialize the timerB
    timerB_init();
    timerB_start_ACLK_div(1);
    timerB_register_cb(ALARM_RETRY, tx_try);

    // 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_IDLE_TO_TX_RX);
    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

    // rise CCA threshold
    cc1101_cfg_carrier_sense_abs_thr(5);

    // 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 RX and TX
    cc1101_cfg_rxoff_mode(CC1101_RXOFF_MODE_IDLE);
    cc1101_cfg_txoff_mode(CC1101_TXOFF_MODE_RX);

    uint8_t table[1] = {CC1101_868MHz_TX_0dBm};
    // table[0] = CC1101_868MHz_TX_m30dBm;
    // table[0] = CC1101_868MHz_TX_m20dBm;
    // table[0] = CC1101_868MHz_TX_m15dBm;
    // table[0] = CC1101_868MHz_TX_m10dBm;
    // table[0] = CC1101_868MHz_TX_m6dBm;
    table[0] = CC1101_868MHz_TX_0dBm;
    // table[0] = CC1101_868MHz_TX_5dBm;
    // table[0] = CC1101_868MHz_TX_7dBm;
    // table[0] = CC1101_868MHz_TX_10dBm;
    // table[0] = CC1101_868MHz_TX_12dBm;
    cc1101_cfg_patable(table, 1);
    cc1101_cfg_pa_power(0);

    // set IDLE state, flush everything, and start rx
    cc1101_cmd_idle();
    cc1101_cmd_flush_rx();
    cc1101_cmd_flush_tx();
    cc1101_cmd_calibrate();

    // configure irq
    cc1101_cfg_gdo0(CC1101_GDOx_SYNC_WORD);
    cc1101_gdo0_int_set_falling_edge();
    cc1101_gdo0_int_clear();
    cc1101_gdo0_int_enable();
    cc1101_gdo0_register_callback(rx_parse);

    // start the machine
    rx_set();

    txframe.length = 0;
}
Esempio n. 9
0
void mac_init(uint8_t channel)
{
    // initialize the unique serial number chip and set node address accordingly
    ds2411_init();
    node_addr = (((uint16_t)ds2411_id.serial1)<<8) + (ds2411_id.serial0);

    // seed the random number generator
    srand(node_addr);

    // reset callbacks
    received_cb = 0x0;
    sent_cb = 0x0;
    error_cb = 0x0;

    // initialize the timerB
    timerB_init();
    timerB_start_ACLK_div(1);
    timerB_register_cb(ALARM_RETRY, check);

    // configure the radio
    cc1100_init();
    cc1100_cmd_idle();

    /* configure the radio behaviour */
    cc1100_cfg_append_status(CC1100_APPEND_STATUS_ENABLE);
    cc1100_cfg_crc_autoflush(CC1100_CRC_AUTOFLUSH_DISABLE);
    cc1100_cfg_white_data(CC1100_DATA_WHITENING_ENABLE);
    cc1100_cfg_crc_en(CC1100_CRC_CALCULATION_ENABLE);
    cc1100_cfg_freq_if(0x0E);
    cc1100_cfg_fs_autocal(CC1100_AUTOCAL_IDLE_TO_TX_RX);
    cc1100_cfg_mod_format(CC1100_MODULATION_GFSK);
    cc1100_cfg_sync_mode(CC1100_SYNCMODE_30_32);
    cc1100_cfg_manchester_en(CC1100_MANCHESTER_DISABLE);
    cc1100_cfg_cca_mode(CC1100_CCA_MODE_RSSI_PKT_RX);

    // freq = 860MHz
    cc1100_write_reg(CC1100_REG_FREQ2, 0x1F);
    cc1100_write_reg(CC1100_REG_FREQ1, 0xDA);
    cc1100_write_reg(CC1100_REG_FREQ0, 0x12);

    //packet length to 61
    cc1100_write_reg(CC1100_REG_PKTLEN, 0x3D);

    // configure the radio channel
    cc1100_cfg_chanspc_e(0x2);
    cc1100_cfg_chanspc_m(0xF8);

    cc1100_write_reg(CC1100_REG_DEVIATN, 0x47);

    // rise CCA threshold
    cc1100_cfg_carrier_sense_abs_thr(5);

    // set channel bandwidth
    cc1100_cfg_chanbw_e(1);
    cc1100_cfg_chanbw_m(3);

    // set data rate
    cc1100_cfg_drate_e(0xB);
    cc1100_cfg_drate_m(0x74);

    // go to RX after RX and TX
    cc1100_cfg_rxoff_mode(CC1100_RXOFF_MODE_IDLE);
    cc1100_cfg_txoff_mode(CC1100_TXOFF_MODE_RX);

    uint8_t table[1];
    table[0] = 0x1E;      // -15dBm   13.4mA
    cc1100_cfg_patable(table, 1);
    cc1100_cfg_pa_power(0);

    // set IDLE state, flush everything, and start rx
    cc1100_cmd_idle();
    cc1100_cmd_flush_rx();
    cc1100_cmd_flush_tx();
    cc1100_cmd_calibrate();

    // configure irq
    cc1100_cfg_gdo0(CC1100_GDOx_SYNC_WORD);
    cc1100_gdo0_int_set_falling_edge();
    cc1100_gdo0_int_clear();
    cc1100_gdo0_int_enable();
    cc1100_gdo0_register_callback(rx_parse);

    // start the machine
    rx_set();

    txframe.length = 0;
}