// Setup reader to card connection // // The setup consists of a three way handshake: // - Receive initialisation vector 7 bits // - Transmit card type 6 bits // - Receive Acknowledge 6 bits static int32_t setup_phase(legic_card_select_t *p_card) { uint8_t len = 0; // init coordination timestamp last_frame_end = GetCountSspClk(); // reset prng legic_prng_init(0); // wait for iv int32_t iv = rx_frame(&len); if((len != 7) || (iv < 0)) { return -1; } // configure prng legic_prng_init(iv); // reply with card type switch(p_card->tagtype) { case 0: tx_frame(0x0D, 6); break; case 1: tx_frame(0x1D, 6); break; case 2: tx_frame(0x3D, 6); break; } // wait for ack int32_t ack = rx_frame(&len); if((len != 6) || (ack < 0)) { return -1; } // validate data switch(p_card->tagtype) { case 0: if(ack != 0x19) return -1; break; case 1: if(ack != 0x39) return -1; break; case 2: if(ack != 0x39) return -1; break; } // During rx the prng is clocked using the variable reader period. // Since rx_frame detects end of frame by detecting a code violation, // the prng is off by one bit period after each rx phase. Hence, tx // code advances the prng by (TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1). // This is not possible for back to back rx, so this quirk reduces // the gap by one period. last_frame_end += TAG_BIT_PERIOD; return 0; }
/** * \brief Handles software-controlled CSMA. * * \param csma_mode CSMA Mode; eg. ED or CS * \param retransmit true if frame re-transmission is requested */ static inline void sw_controlled_csma(csma_mode_t csma_mode, bool retransmit) { if (retransmit) { number_of_tx_retries = 0; /* actual number of retries */ } else { /* no further retries */ number_of_tx_retries = tal_pib.MaxFrameRetries; } /* Handle interframe spacing */ if (csma_mode == NO_CSMA_WITH_IFS) { if (last_frame_length > aMaxSIFSFrameSize) { pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US( macMinLIFSPeriod_def) - IRQ_PROCESSING_DLY_US - PRE_TX_DURATION_US); } else { pal_timer_delay(TAL_CONVERT_SYMBOLS_TO_US( macMinSIFSPeriod_def) - IRQ_PROCESSING_DLY_US - PRE_TX_DURATION_US); } } if ((csma_mode == NO_CSMA_WITH_IFS) || (csma_mode == NO_CSMA_NO_IFS)) { tx_frame(); } else { csma_start(); } }
void send_mesg_test_mode() { lcd_init(); init_push_buttons(); usart_init(); txq_init(); usart_drain_rx(); lcd_puts("Send Mesg Test Mode"); wait_ms(1000); lcd_clear(); char echo_mesg[] = "foobar"; // Assumed to be less than DATA_FRAME_MAX_LEN. while (true) { switch (wait_button("Select Message")) { case mesg_ping: txq_enqueue(signal_start); txq_enqueue(mesg_ping); txq_enqueue(signal_stop); txq_drain(); break; case mesg_echo: txq_enqueue(signal_start); txq_enqueue(mesg_echo); // Copy the echo message into the `control`: strcpy(control.data, echo_mesg); control.data_len = strlen(echo_mesg); // Enqueue the frame. No more frames coming. tx_frame(false); txq_enqueue(signal_start); txq_drain(); break; default: wait_button("Invalid selection."); break; } } }
/* * \brief handling of CCA result. */ void cca_done_handling(void) { set_trx_state(CMD_PLL_ON); /* leave RX_ON */ /* Restore IRQ handling */ trx_irq_init((FUNC_PTR)trx_irq_handler_cb); trx_reg_write(RG_IRQ_MASK, TRX_IRQ_DEFAULT); trx_bit_write(SR_RX_PDT_DIS, RX_ENABLE); /* Enable frame reception. **/ /* Check if channel was idle or busy */ if (trx_bit_read(SR_CCA_STATUS) == CCA_STATUS_CHANNEL_IS_IDLE) { tx_frame(); } else { tal_state = TAL_CSMA_CONTINUE; } }
static int32_t connected_phase(legic_card_select_t *p_card) { uint8_t len = 0; // wait for command int32_t cmd = rx_frame(&len); if(cmd < 0) { return -1; } // check if command is LEGIC_READ if(len == p_card->cmdsize) { // prepare data uint8_t byte = legic_mem[cmd >> 1]; uint8_t crc = calc_crc4(cmd, p_card->cmdsize, byte); // transmit data tx_frame((crc << 8) | byte, 12); return 0; }
//Handler for OI, moved from control. void oi_system() { movement_data_t movement_data; rotation_data_t rotation_data; enum { oi_command_init = 0, oi_command_move = 1, oi_command_rotate = 2, oi_command_play_song = 3, oi_command_dump = 4, oi_command_end_sequence = 5 } oi_command = usart_rx(); txq_enqueue(oi_command); switch (oi_command) { case oi_command_init: oi_init(&(control.oi_state)); break; case oi_command_move: if(rx_frame()) { r_error(error_frame,"Move should not have multiple frames."); } struct { uint16_t speed; uint16_t dist; bool stream; } *move_data = (void *) &control.data; struct { uint16_t dist; uint8_t flag; } *response_move = (void *) &control.data; #warning "Stream functionality to be implemented later." //Stream returns the distance traveled //lcd_puts ("In OI subsystem"); //debug movement_data = move_dist(&(control.oi_state), move_data->dist, move_data->speed); response_move->dist = movement_data.travelled; response_move->flag = movement_data.flag; if (movement_data.flag != 0) { movement_data = move_dist(&(control.oi_state), -20, move_data->speed); response_move->dist += movement_data.travelled; } control.data_len = 3; tx_frame(false); break; case oi_command_rotate: if (rx_frame()) { r_error(error_bad_message, "Rotate should only have one data frame."); } int16_t *angle = &(control.data[0]); // TODO: test if this is the right number of bytes if (control.data_len != 2/*sizeof(*angle)*/) { // TODO: hardcoding to debug r_error(error_bad_message, "Received too much data with rotate " "message."); } struct { uint16_t rotation; } *response_rotation = (void *) &control.data; rotation_data = turn(&(control.oi_state), *angle); response_rotation->rotation = rotation_data.rotated; control.data_len = 2; tx_frame(false); break; //Sing me a song. case oi_command_play_song: #warning "oi_command_play_song is deprecated" ; //assuming that we get two data frames, the first containing the notes and the second containing the durations. int j; struct { uint8_t n; //The number of notes present in the song //char data[n]; uint8_t index; } *song_data = (void *) &control.data; // int j; while(rx_frame()) { //this should happen twice please char tmp_notes[song_data->n]; char tmp_durs[song_data->n]; for(j =0; j<song_data->n; j++) { //tmp_notes[n]; TODO: broken #warning "oi_command_play_song not implemented" } } break; case oi_command_dump: //copies all of the data from OI_UPDATE and transmits to Control. oi_update(&(control.oi_state)); memcpy(control.data, &control.oi_state, sizeof(control.oi_state)); control.data_len = sizeof(control.oi_state); tx_frame(false); break; case oi_command_end_sequence: #warning "oi_command_end_sequence not implemented" // Switch power LED off oi_set_leds(1, 1, 0, 0); wait_ms(50); // Switch power LED to orange oi_set_leds(1, 1, 170, 255); wait_ms(50); // Switch power LED off oi_set_leds(1, 1, 0, 0); wait_ms(50); // Switch power LED to yellow oi_set_leds(1, 1, 70, 255); wait_ms(50); // Switch power LED off oi_set_leds(1, 1, 0, 0); wait_ms(50); // Switch power LED back to default state (from oi_init()) oi_set_leds(1, 1, 7, 255); // Play song songs_load(RICK_ROLL); break; default: r_error(error_bad_message, "Bad OI Command"); break; } }
int meshd_write_mgmt(char *buf, int framelen, void *cookie) { tx_frame(&nlcfg, (unsigned char *) buf, framelen); return framelen; }