inline void crc16_ccitt_readReply(unsigned int numDataBytes) { // shift everything over by 1 to accomodate leading "0" bit. // first, grab address of beginning of array readReply[numDataBytes + 2] = 0; // clear out this spot for the loner bit of // handle readReply[numDataBytes + 4] = 0; // clear out this spot for the loner bit of // crc bits = (unsigned short) &readReply[0]; // shift all bytes and later use only data + handle asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); asm("RRC.b @R5+"); // store loner bit in array[numDataBytes+2] position asm("RRC.b @R5+"); // make first bit 0 readReply[0] &= 0x7f; // compute crc on data + handle bytes readReplyCRC = crc16_ccitt(&readReply[0], numDataBytes + 2); readReply[numDataBytes + 4] = readReply[numDataBytes + 2]; // XOR the MSB of CRC with loner bit. readReply[numDataBytes + 4] ^= __swap_bytes(readReplyCRC); // XOR happens with // MSB of lower // nibble // Just take the resulting bit, not the whole byte readReply[numDataBytes + 4] &= 0x80; unsigned short mask = __swap_bytes(readReply[numDataBytes + 4]); mask >>= 3; mask |= (mask >> 7); mask ^= 0x1020; mask >>= 1; // this is because the loner bit pushes the CRC to the left by 1 // but we don't shift the crc because it should get pushed out by 1 anyway readReplyCRC ^= mask; readReply[numDataBytes + 3] = (unsigned char) readReplyCRC; readReply[numDataBytes + 2] |= (unsigned char) (__swap_bytes(readReplyCRC) & 0x7F); }
int cfg_blob_copy( blob_t *from, void *to ) { size_t len = from->options & BLOB_LENGTH_MASK; if( to != NULL ) { if( is_host_endian( from ) || ( ( from->options & BLOB_LENGTH_MASK ) == 1 ) ) __copy( from, to ); else { __copy( from, to ); if( from->options & BLOB_ARRAY ) switch( len ) { case 2: for( char *limit = to + 2 * from->array.length, *cyc = to; cyc < limit; cyc += 2 ) bswap_16( *( ( uint16_t* ) cyc ) ); break; case 4: for( char *limit = to + 4 * from->array.length, *cyc = to; cyc < limit; cyc += 4 ) bswap_32( *( ( uint32_t* ) cyc ) ); break; default: for( char *limit = to + len * from->array.length, *cyc = to; cyc < limit; cyc += len ) __swap_bytes( cyc, len ); } else switch( len ) { case 2: bswap_16( *( ( uint16_t* ) to ) ); break; case 4: bswap_32( *( ( uint32_t* ) to ) ); break; default: __swap_bytes( to, len ); }; } } if( from->options & BLOB_ARRAY ) return ( len * from->array.length ) else return len; }
/** * For talking to the MCP4822 DAC */ void DAC_updateVoltage(uint16_t channel, uint16_t value) { // Validate channel selection if(channel <= 1) { // Cap value to 12 bits only if(value > 0x0FFF) { value = 0x0FFF; } char txBuf[2]; uint16_t cmd = 0x3000 | (value & 0x0FFF); if(channel) cmd |= 0x8000; txBuf[1] = cmd & 0x00FF; txBuf[0] = __swap_bytes(cmd) & 0x00FF; CLR_BITS(SPI_PORT(OUT),SSEL | nLDAC); // CS~ falling edge, hold nLDAC low SPI_send(txBuf, 2); SET_BITS(SPI_PORT(OUT),SSEL); // CS~ Rising edge. Because nLDAC is low, DAC output changes on rising CS~ edge. } }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// @author NIVIS LLC, Ion Ticus /// @brief Check if message destination is in current subnet /// @return 1 if message remains in subnet, 0 if not /// @remarks /// Access level: Interrupt level\n /// Context: BBR only //////////////////////////////////////////////////////////////////////////////////////////////////// uint8 NLME_IsInSameSubnet( uint16 p_unDestAddr ) { p_unDestAddr = __swap_bytes(p_unDestAddr); for ( uint8 ucIdx = 0; ucIdx < g_stNlme.m_ucToEthRoutesNo; ucIdx ++ ) { if( g_stNlme.m_aToEthRoutes[ucIdx] == p_unDestAddr ) return !g_stNlme.m_ucDefaultIsDLL; } return g_stNlme.m_ucDefaultIsDLL; }
void handle_read(volatile short nextState) { #if SENSOR_DATA_IN_READ_COMMAND //P1OUT &= ~RX_EN_PIN; // turn off comparator TACCTL1 &= ~CCIE; TAR = 0; readReply[DATA_LENGTH_IN_BYTES] = queryReply[0]; // remember to restore // correct RN before doing // crc() readReply[DATA_LENGTH_IN_BYTES+1] = queryReply[1]; // because crc() will shift // bits to add crc16_ccitt_readReply(DATA_LENGTH_IN_BYTES); // leading "0" bit. // DATA_LENGTH_IN_BYTES*8 bits for data + 16 bits for the handle + 16 bits for // the CRC + leading 0 + add one to number of bits for xmit code sendToReader(&readReply[0], ((DATA_LENGTH_IN_BYTES*8)+16+16+1+1)); state = nextState; delimiterNotFound = 1; #elif SIMPLE_READ_COMMAND //P1OUT &= ~RX_EN_PIN; // turn off comparator TACCTL1 &= ~CCIE; TAR = 0; #define USE_COUNTER 1 #if USE_COUNTER readReply[0] = __swap_bytes(read_counter); readReply[1] = read_counter; #else readReply[0] = 0x03; readReply[1] = 0x04; #endif readReply[2] = queryReply[0]; // remember to restore correct RN before doing // crc() readReply[3] = queryReply[1]; // because crc() will shift bits to add crc16_ccitt_readReply(2); // leading "0" bit. // after that sends tagResponse // 16 bits for data + 16 bits for the handle + 16 bits for the CRC + leading 0 // + add one to number of bits for seong's xmit code sendToReader(&readReply[0], 50); state = nextState; delimiterNotFound = 1; // reset #endif }
/** * Use the hardware CRC-CCITT module of the MSP430 to generate a CRC as * per ISO/IEC 13239 CRC16 specification used in ISO 15693. Generating * polynomial is 0x8408, preset value is 0xFFFF. * * CRC is appended to end of transmitCommand array. * * @author Aaron Parks */ unsigned int hw_crc_ccitt(unsigned char* transmitCommand, unsigned int number_of_bytes) { // Preset CRC result as per ISO/IEC 13239 CRCINIRES = 0xFFFF; // Iterate over transmitCommand array unsigned int crc_i; for(crc_i=0; crc_i <number_of_bytes; crc_i++) { // Load next byte into LSB of data input register // TODO: Can this be done faster word-wise? CRCDI_L = transmitCommand[crc_i]; } CRCINIRES = ~CRCINIRES; // Invert bits of result // Store result from bit-order-reversed version of CRCRES transmitCommand[number_of_bytes] = CRCRESR & 0x00FF; transmitCommand[number_of_bytes + 1] = __swap_bytes(CRCRESR) & 0x00FF; return 1; }
int main(void) { //*******************************Timer setup********************************** WDTCTL = WDTPW + WDTHOLD; // Stop Watchdog Timer P1SEL = 0; P2SEL = 0; P1IE = 0; P1IFG = 0; P2IFG = 0; DRIVE_ALL_PINS // set pin directions correctly and outputs to low. // Check power on bootup, decide to receive or sleep. if(!is_power_good()) sleep(); RECEIVE_CLOCK; #if DEBUG_PINS_ENABLED #if USE_2618 DEBUG_PIN5_LOW; #endif #endif #if ENABLE_SLOTS // setup int epc epc = ackReply[2]<<8; epc |= ackReply[3]; // calculate RN16_1 table for (Q = 0; Q < 16; Q++) { rn16 = epc^Q; lfsr(); if (Q > 8) { RN16[(Q<<1)-9] = __swap_bytes(rn16); RN16[(Q<<1)-8] = rn16; } else { RN16[Q] = rn16; } } #endif TACTL = 0; asm("MOV #0000h, R9"); // dest = destorig; #if READ_SENSOR init_sensor(); #endif #if !(ENABLE_SLOTS) queryReplyCRC = crc16_ccitt(&queryReply[0],2); queryReply[3] = (unsigned char)queryReplyCRC; queryReply[2] = (unsigned char)__swap_bytes(queryReplyCRC); #endif #if SENSOR_DATA_IN_ID // this branch is for sensor data in the id ackReply[2] = SENSOR_DATA_TYPE_ID; state = STATE_READ_SENSOR; timeToSample++; #else ackReplyCRC = crc16_ccitt(&ackReply[0], 14); ackReply[15] = (unsigned char)ackReplyCRC; ackReply[14] = (unsigned char)__swap_bytes(ackReplyCRC); #endif #if ENABLE_SESSIONS initialize_sessions(); #endif state = STATE_READY; setup_to_receive(); while (1) { // TIMEOUT! reset timer if (TAR > 0x256 || delimiterNotFound) // was 0x1000 { if(!is_power_good()) { sleep(); } #if SENSOR_DATA_IN_ID // this branch is for sensor data in the id if ( timeToSample++ == 10 ) { state = STATE_READ_SENSOR; timeToSample = 0; } #elif SENSOR_DATA_IN_READ_COMMAND if ( timeToSample++ == 10 ) { state = STATE_READ_SENSOR; timeToSample = 0; } #else #if !(ENABLE_READS) if(!is_power_good()) sleep(); #endif inInventoryRound = 0; state = STATE_READY; #endif #if ENABLE_SESSIONS handle_session_timeout(); #endif #if ENABLE_SLOTS if (shift < 4) shift += 1; else shift = 0; #endif setup_to_receive(); } switch (state) { case STATE_READY: { inInventoryRound = 0; ////////////////////////////////////////////////////////////////////// // process the QUERY command ////////////////////////////////////////////////////////////////////// if ( bits == NUM_QUERY_BITS && ( ( cmd[0] & 0xF0 ) == 0x80 ) ) { handle_query(STATE_REPLY); setup_to_receive(); } ////////////////////////////////////////////////////////////////////// // process the SELECT command ////////////////////////////////////////////////////////////////////// // @ short distance has slight impact on performance else if ( bits >= 44 && ( ( cmd[0] & 0xF0 ) == 0xA0 ) ) { handle_select(STATE_READY); delimiterNotFound = 1; } // select command ////////////////////////////////////////////////////////////////////// // got >= 22 bits, and it's not the beginning of a select. just reset. ////////////////////////////////////////////////////////////////////// else if ( bits >= MAX_NUM_QUERY_BITS && ( ( cmd[0] & 0xF0 ) != 0xA0 ) ) { do_nothing(); state = STATE_READY; delimiterNotFound = 1; } break; } case STATE_ARBITRATE: { ////////////////////////////////////////////////////////////////////// // process the QUERY command ////////////////////////////////////////////////////////////////////// if ( bits == NUM_QUERY_BITS && ( ( cmd[0] & 0xF0 ) == 0x80 ) ) { handle_query(STATE_REPLY); setup_to_receive(); } ////////////////////////////////////////////////////////////////////// // got >= 22 bits, and it's not the beginning of a select. just reset. ////////////////////////////////////////////////////////////////////// //else if ( bits >= NUM_QUERY_BITS ) else if ( bits >= MAX_NUM_QUERY_BITS && ( ( cmd[0] & 0xF0 ) != 0xA0 ) ) { do_nothing(); state = STATE_READY; delimiterNotFound = 1; } // this state handles query, queryrep, queryadjust, and select commands. ////////////////////////////////////////////////////////////////////// // process the QUERYREP command ////////////////////////////////////////////////////////////////////// else if ( bits == NUM_QUERYREP_BITS && ( ( cmd[0] & 0x06 ) == 0x00 ) ) { handle_queryrep(STATE_REPLY); delimiterNotFound = 1; } // queryrep command ////////////////////////////////////////////////////////////////////// // process the QUERYADJUST command ////////////////////////////////////////////////////////////////////// else if ( bits == NUM_QUERYADJ_BITS && ( ( cmd[0] & 0xF8 ) == 0x48 ) ) { handle_queryadjust(STATE_REPLY); setup_to_receive(); } // queryadjust command ////////////////////////////////////////////////////////////////////// // process the SELECT command ////////////////////////////////////////////////////////////////////// // @ short distance has slight impact on performance else if ( bits >= 44 && ( ( cmd[0] & 0xF0 ) == 0xA0 ) ) { handle_select(STATE_READY); delimiterNotFound = 1; } // select command break; } case STATE_REPLY: { // this state handles query, query adjust, ack, and select commands /////////////////////////////////////////////////////////////////////// // process the ACK command /////////////////////////////////////////////////////////////////////// if ( bits == NUM_ACK_BITS && ( ( cmd[0] & 0xC0 ) == 0x40 ) ) { #if ENABLE_READS handle_ack(STATE_ACKNOWLEDGED); setup_to_receive(); #elif SENSOR_DATA_IN_ID handle_ack(STATE_ACKNOWLEDGED); delimiterNotFound = 1; // reset #else // this branch for hardcoded query/acks handle_ack(STATE_ACKNOWLEDGED); //delimiterNotFound = 1; // reset setup_to_receive(); #endif } ////////////////////////////////////////////////////////////////////// // process the QUERY command ////////////////////////////////////////////////////////////////////// if ( bits == NUM_QUERY_BITS && ( ( cmd[0] & 0xF0 ) == 0x80 ) ) { // i'm supposed to stay in state_reply when I get this, but if I'm // running close to 1.8v then I really need to reset and get in the // sleep, which puts me back into state_arbitrate. this is complete // a violation of the protocol, but it sure does make everything // work better. - polly 8/9/2008 handle_query(STATE_REPLY); setup_to_receive(); } ////////////////////////////////////////////////////////////////////// // process the QUERYREP command ////////////////////////////////////////////////////////////////////// else if ( bits == NUM_QUERYREP_BITS && ( ( cmd[0] & 0x06 ) == 0x00 ) ) { do_nothing(); state = STATE_ARBITRATE; setup_to_receive(); } // queryrep command ////////////////////////////////////////////////////////////////////// // process the QUERYADJUST command ////////////////////////////////////////////////////////////////////// else if ( bits == NUM_QUERYADJ_BITS && ( ( cmd[0] & 0xF8 ) == 0x48 ) ) { handle_queryadjust(STATE_REPLY); delimiterNotFound = 1; } // queryadjust command ////////////////////////////////////////////////////////////////////// // process the SELECT command ////////////////////////////////////////////////////////////////////// else if ( bits >= 44 && ( ( cmd[0] & 0xF0 ) == 0xA0 ) ) { handle_select(STATE_READY); delimiterNotFound = 1; } // select command else if ( bits >= MAX_NUM_QUERY_BITS && ( ( cmd[0] & 0xF0 ) != 0xA0 ) && ( ( cmd[0] & 0xF0 ) != 0x80 ) ) { do_nothing(); state = STATE_READY; delimiterNotFound = 1; } break; } case STATE_ACKNOWLEDGED: { // responds to query, ack, request_rn cmds // takes action on queryrep, queryadjust, and select cmds ///////////////////////////////////////////////////////////////////// // process the REQUEST_RN command ////////////////////////////////////////////////////////////////////// if ( bits >= NUM_REQRN_BITS && ( cmd[0] == 0xC1 ) ) { #if 1 handle_request_rn(STATE_OPEN); setup_to_receive(); #else handle_request_rn(STATE_READY); delimiterNotFound = 1; #endif } #if 1 ////////////////////////////////////////////////////////////////////// // process the QUERY command ////////////////////////////////////////////////////////////////////// if ( bits == NUM_QUERY_BITS && ( ( cmd[0] & 0xF0 ) == 0x80 ) ) { handle_query(STATE_REPLY); delimiterNotFound = 1; } /////////////////////////////////////////////////////////////////////// // process the ACK command /////////////////////////////////////////////////////////////////////// // this code doesn't seem to get exercised in the real world. if i ever // ran into a reader that generated an ack in an acknowledged state, // this code might need some work. //else if ( bits == 20 && ( ( cmd[0] & 0xC0 ) == 0x40 ) ) else if ( bits == NUM_ACK_BITS && ( ( cmd[0] & 0xC0 ) == 0x40 ) ) { handle_ack(STATE_ACKNOWLEDGED); setup_to_receive(); } ////////////////////////////////////////////////////////////////////// // process the QUERYREP command ////////////////////////////////////////////////////////////////////// else if ( bits == NUM_QUERYREP_BITS && ( ( cmd[0] & 0x06 ) == 0x00 ) ) { // in the acknowledged state, rfid chips don't respond to queryrep // commands do_nothing(); state = STATE_READY; delimiterNotFound = 1; } // queryrep command ////////////////////////////////////////////////////////////////////// // process the QUERYADJUST command ////////////////////////////////////////////////////////////////////// else if ( bits == NUM_QUERYADJ_BITS && ( ( cmd[0] & 0xF8 ) == 0x48 ) ) { do_nothing(); state = STATE_READY; delimiterNotFound = 1; } // queryadjust command ////////////////////////////////////////////////////////////////////// // process the SELECT command ////////////////////////////////////////////////////////////////////// else if ( bits >= 44 && ( ( cmd[0] & 0xF0 ) == 0xA0 ) ) { handle_select(STATE_READY); delimiterNotFound = 1; } // select command ////////////////////////////////////////////////////////////////////// // process the NAK command ////////////////////////////////////////////////////////////////////// else if ( bits >= 10 && ( cmd[0] == 0xC0 ) ) { do_nothing(); state = STATE_ARBITRATE; delimiterNotFound = 1; } ////////////////////////////////////////////////////////////////////// // process the READ command ////////////////////////////////////////////////////////////////////// // warning: won't work for read addrs > 127d if ( bits == NUM_READ_BITS && ( cmd[0] == 0xC2 ) ) { handle_read(STATE_ARBITRATE); state = STATE_ARBITRATE; delimiterNotFound = 1 ; } // FIXME: need write, kill, lock, blockwrite, blockerase ////////////////////////////////////////////////////////////////////// // process the ACCESS command ////////////////////////////////////////////////////////////////////// if ( bits >= 56 && ( cmd[0] == 0xC6 ) ) { do_nothing(); state = STATE_ARBITRATE; delimiterNotFound = 1 ; } #endif else if ( bits >= MAX_NUM_READ_BITS ) { state = STATE_ARBITRATE; delimiterNotFound = 1 ; } #if 0 // kills performance ... else if ( bits >= 44 ) { do_nothing(); state = STATE_ARBITRATE; delimiterNotFound = 1; } #endif break; } case STATE_OPEN: { // responds to query, ack, req_rn, read, write, kill, access, // blockwrite, and blockerase cmds // processes queryrep, queryadjust, select cmds ////////////////////////////////////////////////////////////////////// // process the READ command ////////////////////////////////////////////////////////////////////// // warning: won't work for read addrs > 127d if ( bits == NUM_READ_BITS && ( cmd[0] == 0xC2 ) ) { handle_read(STATE_OPEN); // note: setup_to_receive() et al handled in handle_read } ////////////////////////////////////////////////////////////////////// // process the REQUEST_RN command ////////////////////////////////////////////////////////////////////// else if ( bits >= NUM_REQRN_BITS && ( cmd[0] == 0xC1 ) ) { handle_request_rn(STATE_OPEN); setup_to_receive(); } ////////////////////////////////////////////////////////////////////// // process the QUERY command ////////////////////////////////////////////////////////////////////// if ( bits == NUM_QUERY_BITS && ( ( cmd[0] & 0xF0 ) == 0x80 ) ) { handle_query(STATE_REPLY); delimiterNotFound = 1; } ////////////////////////////////////////////////////////////////////// // process the QUERYREP command ////////////////////////////////////////////////////////////////////// else if ( bits == NUM_QUERYREP_BITS && ( ( cmd[0] & 0x06 ) == 0x00 ) ) { do_nothing(); state = STATE_READY; setup_to_receive(); } // queryrep command ////////////////////////////////////////////////////////////////////// // process the QUERYADJUST command ////////////////////////////////////////////////////////////////////// else if ( bits == 9 && ( ( cmd[0] & 0xF8 ) == 0x48 ) ) { do_nothing(); state = STATE_READY; delimiterNotFound = 1; } // queryadjust command /////////////////////////////////////////////////////////////////////// // process the ACK command /////////////////////////////////////////////////////////////////////// else if ( bits == NUM_ACK_BITS && ( ( cmd[0] & 0xC0 ) == 0x40 ) ) { handle_ack(STATE_OPEN); delimiterNotFound = 1; } ////////////////////////////////////////////////////////////////////// // process the SELECT command ////////////////////////////////////////////////////////////////////// else if ( bits >= 44 && ( ( cmd[0] & 0xF0 ) == 0xA0 ) ) { handle_select(STATE_READY); delimiterNotFound = 1; } // select command ////////////////////////////////////////////////////////////////////// // process the NAK command ////////////////////////////////////////////////////////////////////// else if ( bits >= 10 && ( cmd[0] == 0xC0 ) ) { handle_nak(STATE_ARBITRATE); delimiterNotFound = 1; } break; } case STATE_READ_SENSOR: { #if SENSOR_DATA_IN_READ_COMMAND read_sensor(&readReply[0]); // crc is computed in the read state RECEIVE_CLOCK; state = STATE_READY; delimiterNotFound = 1; // reset #elif SENSOR_DATA_IN_ID read_sensor(&ackReply[3]); RECEIVE_CLOCK; ackReplyCRC = crc16_ccitt(&ackReply[0], 14); ackReply[15] = (unsigned char)ackReplyCRC; ackReply[14] = (unsigned char)__swap_bytes(ackReplyCRC); state = STATE_READY; delimiterNotFound = 1; // reset #endif break; } // end case } // end switch } // while loop }
//----------------------------------------------------------------------------------------- // BQ27421_GetAverageCurrent //----------------------------------------------------------------------------------------- // Diese Funktion liest den aktuellen (über 1 Sekunde) gemittelten Strom in mA //----------------------------------------------------------------------------------------- int BQ27421_GetAverageCurrent(void) { int iRetValue = 0; BQ27421_READ_REG(BQ272421_I2C_ADR, 0x10, &iRetValue, 2); return __swap_bytes(iRetValue); }
//----------------------------------------------------------------------------------------- // BQ27421_GetAkkuSpannung //----------------------------------------------------------------------------------------- // Diese Funktion liest die Akku-Spannung aus und gibt diese in mV zurück //----------------------------------------------------------------------------------------- int BQ27421_GetAkkuSpannung(void) { WORD wRetValue; BQ27421_READ_REG(BQ272421_I2C_ADR, 0x04, &wRetValue, 2); return __swap_bytes(wRetValue); }
void handle_query(volatile short nextState) { TAR = 0; #if (!ENABLE_SLOTS) && (!ENABLE_SESSIONS) while ( TAR < 90 ); // if bit test is 22 //P1OUT &= ~RX_EN_PIN; // turn off comparator TACCTL1 &= ~CCIE; // Disable capturing and comparing interrupt TAR = 0; #elif (!ENABLE_SLOTS) && ENABLE_SESSIONS while ( TAR < 160 ); // if bit test is 22 //P1OUT &= ~RX_EN_PIN; // turn off comparator TACCTL1 &= ~CCIE; // Disable capturing and comparing interrupt TAR = 0; #else //P1OUT &= ~RX_EN_PIN; // turn off comparator TACCTL1 &= ~CCIE; // Disable capturing and comparing interrupt TAR = 0; #endif // set up for TRcal if ( cmd[0] & BIT3) { divideRatio = 21;//64/3; } else { divideRatio = 8; } // set up for subcarrier symbol subcarrierNum = cmd[0] & (BIT2 | BIT1); if (subcarrierNum == 0) { subcarrierNum = 1; } else if ( subcarrierNum == 2 ) { subcarrierNum = 2; } else if (subcarrierNum == 4) { subcarrierNum = 4; } else { subcarrierNum = 8; } // set up for TRext if (cmd[0] & BIT0) { TRext = 1; } else { TRext = 0; } #if ENABLE_SESSIONS #if 1 // command-specific bit masks #define QUERY_SEL_MASK 0xC0 #define QUERY_SESSION_MASK 0x30 #define QUERY_TARGET_MASK 0x08 // command-specific bit flags #define QUERY_SEL_SL 0xC0 #define QUERY_SEL_NOTSL 0x80 unsigned short sel = cmd[1] & QUERY_SEL_MASK; unsigned short session = (cmd[1] & QUERY_SESSION_MASK) >> 4; unsigned short target = cmd[1] & QUERY_TARGET_MASK; unsigned short match = 0; #define TARGETISEQUAL(t,s) \ ((t == 0x00 && s == SESSION_STATE_A) || (t == 0x08 && s == SESSION_STATE_B)) // if we are already in an inventory round and the session matches the // previous session, invert the session inventory flag if ( state == STATE_ACKNOWLEDGED || state == STATE_OPEN || state == STATE_SECURED ) { if ( session == previous_session ) { // invert session's inventory flag if ( session_table[session] == SESSION_STATE_A ) session_table[session] = SESSION_STATE_B; else session_table[session] = SESSION_STATE_A; } } // now figure out if the SL and session flags match. Let's look at the SL flag // first. if ( sel < QUERY_SEL_NOTSL || sel == QUERY_SEL_SL && SL == SL_ASSERTED || sel == QUERY_SEL_NOTSL && SL == SL_NOT_ASSERTED ) { // SL flag matches -- now how about the session flag? if ( TARGETISEQUAL(target,session_table[session]) ) { // session match too match = 1; } } if ( ! match ) { // no matching SL/session flags. don't respond and transistion to READY // state. TACCTL1 &= ~CCIE; // Disable capturing and comparing interrupt TAR = 0; state = STATE_READY; return; } // OK, got matching SL and session inventory flags, so we're in this inventory // round. save the session to the previous_session variable in case this is a // new session. previous_session = session; #else while ( TAR < 140 ); TAR = 0; #endif #else // we don't care about SL or session inventory flags at all. just proceed // as if we have matched on them. #endif #if ENABLE_SLOTS // next step is to built a slot counter // parse for Q number and choose a Q value randomly Q = (cmd[1] & 0x07)<<1; if ((cmd[2] & 0x80) == 0x80) Q += 0x01; // pick Q randomly slot_counter = Q >> shift; // HACK ALERT: the Impinj reader seems to output at least two Queries before // it sends along an Ack. If I followed the spec, I might well reply to the // first Query but not the second, owing to a nonzero slot counter. In this // case the reader would just send along QueryReps until the slot counter got // to zero, and I'd emit another response. Problem is, we're a // power-constrained device and we don't necessarily have the ability to // respond to a list of QueryReps. Therefore, I will check to see if I'm in an // inventory round -- that is, I've already seen a query -- and if I am, // pretend my slot counter is zero and respond right away. // slot counter built and it's 0. we can send a reply! if ( inInventoryRound == 1 || slot_counter == 0) { // compute a RN16 loadRN16(); // compute the CRC queryReplyCRC = crc16_ccitt(&queryReply[0],2); queryReply[3] = (unsigned char)queryReplyCRC; queryReply[2] = (unsigned char)__swap_bytes(queryReplyCRC); TACCTL1 &= ~CCIE; // Disable capturing and comparing interrupt while ( TAR < 140 ); TAR = 0; // send out the packet, and transition to STATE_REPLY sendToReader(&queryReply[0], 17); state = nextState; // mix up the RN16 table a bit for next time mixupRN16(); } // slot counter isn't 0, so we don't send a reply. We wait for a // followup QueryRep or QueryAdjust command. In the meantime, // we transition to STATE_ARBITRATE. else { TACCTL1 &= ~CCIE; // Disable capturing and comparing interrupt TAR = 0; state = STATE_ARBITRATE; } inInventoryRound = 1; #else // we don't care about slots, so just send the packet and go to STATE_REPLY. sendToReader(&queryReply[0], 17); state = nextState; #endif }
void handle_queryadjust(volatile short nextState) { TAR = 0; #if !(ENABLE_SLOTS) && !(ENABLE_SESSIONS) while ( TAR < 300 ); //P1OUT &= ~RX_EN_PIN; // turn off comparator TACCTL1 &= ~CCIE; TAR = 0; #endif #if ENABLE_SESSIONS // command-specific bit masks #define QUERYADJ_SESSION_MASK 0x0C unsigned short session = (cmd[0] & QUERYADJ_SESSION_MASK) >> 1; if ( session != previous_session ) { // drop the packet, but stay in the same state TACCTL1 &= ~CCIE; // Disable capturing and comparing interrupt TAR = 0; return; } // if we got this packet in ACKNOWLEDGED, OPEN, or SECURED states, invert the // session flag and transition to STATE_READY to take myself out of this // inventory round. if ( state == STATE_ACKNOWLEDGED || state == STATE_OPEN || state == STATE_SECURED ) { // invert session's inventory flag if ( session_table[session] == SESSION_STATE_A ) session_table[session] = SESSION_STATE_B; else session_table[session] = SESSION_STATE_A; state = STATE_READY; TACCTL1 &= ~CCIE; // Disable capturing and comparing interrupt TAR = 0; return; } #endif #if ENABLE_SLOTS #define QUERYADJ_UPDNB0_MASK 0x01 #define QUERYADJ_UPDNB1_MASK 0xC0 unsigned char updn = (cmd[0] & QUERYADJ_UPDNB0_MASK) << 2; unsigned char tmp = (cmd[1] & QUERYADJ_UPDNB1_MASK) >> 6; updn |= tmp; if ( Q == 0xf && updn == 0x3 ) updn = 0x0; if ( Q == 0x0 && updn == 0x1 ) updn = 0x0; if ( updn == 0x6 ) Q += 1; else if ( updn == 0x3 ) Q -= 1; else if ( updn != 0x0 ) { // impinj likes to send me plenty of updn values of 0x01, which isn't // valid. Spec says to ignore the command in these cases. return; } // pick Q randomly slot_counter = Q >> shift; // slot counter built and it's 0. we can send a reply! if (slot_counter == 0) { // compute a RN16 loadRN16(); // compute a CRC queryReplyCRC = crc16_ccitt(&queryReply[0],2); queryReply[3] = (unsigned char)queryReplyCRC; queryReply[2] = (unsigned char)__swap_bytes(queryReplyCRC); TACCTL1 &= ~CCIE; // Disable capturing and comparing interrupt TAR = 0; // send out the packet, and transition to STATE_REPLY sendToReader(&queryReply[0], 17); state = nextState; // mix up the RN16 table a bit for next time mixupRN16(); } else { // slot counter isn't 0, so we don't send a reply. We wait for a // followup QueryRep or QueryAdjust command. In the meantime, // we transition to STATE_ARBITRATE. state = STATE_ARBITRATE; } #else // we don't care about slots, so just send the packet and go to STATE_REPLY. sendToReader(&queryReply[0], 17); state = nextState; #endif }
unsigned int hw_crc_validate(unsigned char* receiveCommand, unsigned int number_of_bytes) { // Preset CRC result as per ISO/IEC 13239 CRCINIRES = 0xFFFF; // if(number_of_bytes < 2) return 0; // Iterate over transmitCommand array //In essence we calculate the CRC and then will check it with the one appended to the receiveCommand unsigned int crc_i; for(crc_i = 0; crc_i < number_of_bytes - 2; crc_i++) { // Load next byte into LSB of data input register // TODO: Can this be done faster word-wise? CRCDI_L = receiveCommand[crc_i]; } CRCINIRES = ~CRCINIRES; // Invert bits of result // Checks result from bit-order-reversed version of CRCRES to the received CRC (Last 2 bytes of receiveCommand) if((receiveCommand[number_of_bytes - 2] == (CRCRESR & 0x00FF)) && (receiveCommand[number_of_bytes - 1] == (__swap_bytes(CRCRESR) & 0x00FF))) { return (number_of_bytes - 2); }else //toggle_led_2(); return 0; }