www.pudn.com > EM4469firmware.zip > level4.c


/* 
*------------------------------------------------------------------------------- 
*--  RCSId: $Id: level4.c,v 0.17 2003-10-10 10:55:39+02 mjg Exp mjg $ 
*--         $Name:  $ 
*------------------------------------------------------------------------------- 
*-- level4.c - UART Communication Routines  
*------------------------------------------------------------------------------- 
*-- $Log: level4.c,v $ 
*-- Revision 0.17  2003-10-10 10:55:39+02  mjg 
*-- *** empty log message *** 
*-- 
*-- Revision 0.16  2003-08-21 16:00:21+02  mjg 
*-- RTF capture problem 
*-- 
*-- Revision 0.15  2003-08-20 10:53:20+02  mjg 
*-- to redesign SearchPattern 
*-- 
*-- Revision 0.14  2003-08-20 10:00:46+02  mjg 
*-- to add debug features 
*-- 
*-- Revision 0.13  2003-08-07 08:01:29+02  mjg 
*-- *** empty log message *** 
*-- 
*-- Revision 0.11  2003-07-22 13:27:42+02  mjg 
*-- cloned firmware 
*-- 
*------------------------------------------------------------------------------- 
*/ 
 
#include  
#include  
#include  
#include  
#include  
 
#include "level4.h" 
#include "level2.h" 
#include "level1.h" 
 
//-------------------------------------------------------------- 
//global declarations 
 
 
uint8_t volatile uart_command;          // command handshake value 
                                        // set by UART RECV 
                                        // reset by main() when done 
 
uint8_t read_tag_memory_word_address;   // address of Read cmd 
uint16_t read_tag_memory_word_low;      // Read Cmd content low 
uint16_t read_tag_memory_word_hi;       // Read Cmd content hi 
 
uint16_t write_tag_memory_word_address; // address of Write Tag cmd 
uint16_t write_tag_memory_word_low;     // low word of Write Tag cmd 
uint16_t write_tag_memory_word_hi;      // hi word of Write Tag cmd 
 
uint16_t write_tag_memory_login_low;    // low word of Login cmd 
uint16_t write_tag_memory_login_hi;     // hi word of Login cmd 
 
uint8_t write_tag_memory_forward_link;  // forward item of Forward link cmd 
 
uint16_t read_only_word_low;            // Read Only Cmd content low 
uint16_t read_only_word_hi;             // Read Only Cmd content hi 
 
 
uint8_t switch_coil_byte;               // switch item of Set Coil cmd 
 
uint8_t config_data_rate;               // see EM4469 spec 
uint8_t config_encoder;                 // see EM4469 spec 
uint8_t config_psk_carrier;             // see EM4469 spec 
uint8_t config_delayed;                 // see EM4469 spec 
uint8_t config_lwr;                     // see EM4469 spec 
uint8_t config_raw;                     // see EM4469 spec 
uint8_t config_forward_link;            // 0=4050 type, 1=other 
uint8_t config_write_conf;              // 1=write this configuration into the EEPROM 
 
uint8_t * read_ptr;                     //debug capture pulse lengths uart data pointer 
uint8_t volatile read_pos;              //debug capture pulse lengths uart read counter 
 
uint8_t fwd_set_0;                      // forwadlink pulse length values to be set 
uint8_t fwd_set_A; 
uint8_t fwd_set_B; 
uint8_t fwd_set_C; 
uint8_t fwd_set_D; 
uint8_t fwd_set_E; 
uint8_t fwd_set_F; 
 
uint8_t debug_mode; 
 
//-------------------------------------------------------------- 
//local declarations 
 
#define UART_IN_BUFFER_SIZE 32             // incoming data uart buffer reserved size 
#define UART_OUT_BUFFER_SIZE 250           // outgoing data uart buffer reserved size 
 
uint8_t volatile uart_in_buffer[UART_IN_BUFFER_SIZE]; // input cyclic buffer 
uint8_t volatile uart_in_read;                        // input read index 
uint8_t volatile uart_in_end;                         // input message read index 
uint8_t volatile uart_in_write;                       // input write index 
uint8_t volatile uart_in_overflow;                    // input buffer overflow 
uint8_t volatile uart_in_error;                       // input buffer parity error, ... 
 
uint8_t volatile uart_out_buffer[UART_OUT_BUFFER_SIZE];   // output buffer 
uint8_t volatile uart_out_read;                       // output read index 
uint8_t volatile uart_out_write;                      // output write index 
uint8_t volatile uart_out_end;                        // last output write index 
 
uint8_t volatile uart_read_bytes;       // number of bytes to read before parsing 
uint8_t volatile uart_read_msg_bytes;   // actual number of bytes (msg position no.2) 
 
//UART_STATE - enum is errorneous in gcc+sim/debug 
#define UART_EMPTY           1          // no bytes are pending 
#define UART_READ_SIZE       2          // try to analyze incoming message size from pending bytes 
#define UART_READ_BYTES      3          // try to analyze body and ETX of message from pending bytes 
#define UART_WAIT_ERROR_SENT 4          // something is wrong within analysed pending bytes 
#define UART_VALID           5          // known message format was detected, rest is still pending 
 
uint8_t uart_state;                     // current state of incoming message analysis 
 
// ================================================================== 
 
void IncWriteOutIndex(void); 
uint8_t ParseMessage(void); 
void FormatResponse_ReadTagMemory(uint8_t ack); 
void FormatResponse_ReadOnly(uint8_t ack); 
void FormatResponse_Status(uint8_t ack); 
  
 
// ================================================================== 
// uart byte receive interrupt 
 
SIGNAL (SIG_UART_RECV) 
{ 
  uart_in_buffer[uart_in_write++] = UDR;               //store byte into cyclic buffer 
 
  if (uart_in_write == UART_IN_BUFFER_SIZE) 
    uart_in_write = 0; 
 
  if (uart_in_write == uart_in_read) {   
    uart_in_overflow = 1;                              //set flag in overflow 
    //block reception until some bytes are parsed out 
  } 
 
  if ((UCSRA & ((1<= 3) || (c <= 9)) { 
        uart_read_bytes = c; 
        uart_read_msg_bytes = c; 
        uart_state = UART_READ_BYTES; 
      } else { 
        result = ERR_UART_INTERBYTE_ERR; 
        uart_state = UART_WAIT_ERROR_SENT; 
      } 
      break; 
 
    case UART_READ_BYTES :           //read specified size bytes to allow  
 
      if (--uart_read_bytes == 0) {  //last byte - ETX expected 
        //check ETX 
        if (c == 0x03) { 
          result = UART_MESSAGE_OK; 
          uart_state = UART_VALID; 
          uart_in_end = ptr; 
        } else { 
          result = ERR_UART_NO_ETX; 
          uart_state = UART_WAIT_ERROR_SENT; 
        } 
      } 
      break; 
    }; 
 
    if(++ptr == UART_IN_BUFFER_SIZE) 
      ptr = 0; 
  } 
 
  if (uart_state == UART_WAIT_ERROR_SENT) { 
    uart_in_read = uart_in_write;      //dropped =async 
    return result; 
  } 
 
  if (uart_state == UART_VALID) { 
    result = ParseMessage();            //parse message and commit the command 
    uart_in_read = ptr; 
    return result; 
  } 
  return result; 
} 
 
 
// ================================================================== 
// parses valid message format and checks size according to the command type 
 
uint8_t ParseMessage(void) { 
 
  uint8_t byte = 0; 
  uint8_t ptr = uart_in_read; 
  uint8_t ptr2 = 0, c; 
  uint8_t temp_buffer[UART_IN_BUFFER_SIZE]; 
   
  //compute checksum 
  byte = uart_in_buffer[ptr]; 
 
  while (ptr != uart_in_end) { 
    c = uart_in_buffer[ptr++]; 
    if(ptr == UART_IN_BUFFER_SIZE)  
      ptr = 0; 
 
    byte ^= c; 
    temp_buffer[ptr2++] = c;     
  } 
 
  if (byte == 0) {  //checksum ok 
 
    byte = temp_buffer[2]; 
 
    switch(byte) { 
 
      case 0x80 :                               //Read Tag Memory 
        if (uart_read_msg_bytes != 4) 
          return ERR_UART_INTERBYTE_ERR; 
        read_tag_memory_word_address = temp_buffer[3]; 
        break; 
 
      case 0x81 :                               //Write Tag  
        if (uart_read_msg_bytes != 8) 
          return ERR_UART_INTERBYTE_ERR; 
        write_tag_memory_word_address = temp_buffer[3]; 
        write_tag_memory_word_low = ((uint16_t)temp_buffer[5] << 8) + temp_buffer[4]; 
        write_tag_memory_word_hi  = ((uint16_t)temp_buffer[7] << 8) + temp_buffer[6]; 
        break; 
 
      case 0x82 :                               //Login 
        if (uart_read_msg_bytes != 7) 
          return ERR_UART_INTERBYTE_ERR; 
        write_tag_memory_login_low = temp_buffer[3]; 
        write_tag_memory_login_low = (write_tag_memory_login_low << 8) + temp_buffer[4]; 
        write_tag_memory_login_hi  = temp_buffer[5]; 
        write_tag_memory_login_hi  = (write_tag_memory_login_hi << 8) + temp_buffer[6]; 
        break; 
 
      case 0x83 :                               //Disable 
        if (uart_read_msg_bytes != 3) 
          return ERR_UART_INTERBYTE_ERR; 
        break; 
 
      case 0x84 :                               //Forward link 
        if (uart_read_msg_bytes != 4) 
          return ERR_UART_INTERBYTE_ERR; 
        write_tag_memory_forward_link = temp_buffer[3]; 
        break; 
 
      case 0x85 :                               //Read Only Continuous mode 
        if (uart_read_msg_bytes != 3) 
          return ERR_UART_INTERBYTE_ERR; 
        break; 
 
      case 0x86 :                               //Read Only Continuous mode 
        if (uart_read_msg_bytes != 3) 
          return ERR_UART_INTERBYTE_ERR; 
        break; 
 
      case 0xF8 :                               //Send Capture Data 
        if (uart_read_msg_bytes != 3) 
          return ERR_UART_INTERBYTE_ERR; 
        break; 
 
      case 0xF9 :                               //Toggle debug mode 
        if (uart_read_msg_bytes != 4) 
          return ERR_UART_INTERBYTE_ERR; 
        debug_mode = temp_buffer[3]; 
        break; 
 
      case 0xFA :                               //Forward link pulses tuning 
        if (uart_read_msg_bytes != 0xA) 
          return ERR_UART_INTERBYTE_ERR; 
        fwd_set_0 = temp_buffer[3]; 
        fwd_set_A = temp_buffer[4]; 
        fwd_set_B = temp_buffer[5]; 
        fwd_set_C = temp_buffer[6]; 
        fwd_set_D = temp_buffer[7]; 
        fwd_set_E = temp_buffer[8]; 
        fwd_set_F = temp_buffer[9]; 
        break; 
 
      case 0xFB :                               //Reader Read Configuration 
        if (uart_read_msg_bytes != 3) 
          return ERR_UART_INTERBYTE_ERR; 
        break; 
 
      case 0xFC :                               //Reader Write Configuration 
        if (uart_read_msg_bytes != 7) 
          return ERR_UART_INTERBYTE_ERR; 
        config_data_rate = temp_buffer[3] & 0x3F; 
        config_encoder = ((temp_buffer[4] & 0x03) << 2) | (temp_buffer[3] >> 6); 
        config_psk_carrier = (temp_buffer[4] >> 2) & 0x03; 
        config_delayed = (temp_buffer[4] >> 4) & 0x03; 
        config_lwr = ((temp_buffer[5] & 0x03) << 2) | (temp_buffer[4] >> 6); 
        config_raw = (temp_buffer[5] >> 6) & 0x01; 
        config_forward_link = (temp_buffer[5] >> 3) & 0x01; 
        config_write_conf = (temp_buffer[5] >> 2) & 0x01; 
        break; 
 
      case 0xFE :                               //Switch Coil 
        if (uart_read_msg_bytes != 4) 
          return ERR_UART_INTERBYTE_ERR; 
        switch_coil_byte = temp_buffer[3]; 
        break; 
 
      case 0xFD :                               //Reader Status 
        if (uart_read_msg_bytes != 3) 
          return ERR_UART_INTERBYTE_ERR; 
        break; 
 
      default :                                 //Unknown command 
        return ERR_UART_UNKNOWN_CMD; 
    } 
 
    //command was parsed successfully 
 
    uart_command = byte; 
    return UART_MESSAGE_OK; 
  } else {   //bad checksum 
    return ERR_UART_BAD_CRC; 
  } 
} 
 
 
// ================================================================== 
// send response  
 
void SendResponse(uint8_t ack) { 
 
  if (ack == 0) SetLEDOff(); else SetLEDOn(); 
 
  while ( (UCSRB & (1<>8); 
  IncWriteOut((uint8_t)word_hi); 
  IncWriteOut(word_hi>>8); 
 
  IncWriteOut(0x09 ^ cmd ^ ack ^ address ^ (word_low & 0xFF) ^ 
                         (word_low >> 8) ^ (word_hi & 0xFF) ^ 
                         (word_hi >> 8) ); 
  IncWriteOut(0x03); 
  SendResponse(ack); 
} 
 
// ================================================================== 
 
void FormatResponse_Short(uint8_t cmd, uint8_t ack) { 
 
  IncWriteOut(0x02); 
  IncWriteOut(0x04); 
  IncWriteOut(cmd); 
  IncWriteOut(ack); 
  IncWriteOut(0x04 ^ cmd ^ ack);   
  IncWriteOut(0x03); 
  SendResponse(ack); 
} 
 
// ================================================================== 
 
void FormatResponse_Word(uint8_t ack, uint8_t cmd, uint16_t word_low, uint16_t word_hi) { 
 
  IncWriteOut(0x02); 
  IncWriteOut(0x08); 
  IncWriteOut(cmd); 
  IncWriteOut(ack); 
  IncWriteOut((uint8_t)word_low); 
  IncWriteOut(word_low>>8); 
  IncWriteOut((uint8_t)word_hi); 
  IncWriteOut(word_hi>>8); 
 
  IncWriteOut(0x08 ^ cmd ^ ack ^ 
                         (word_low & 0xFF) ^ (word_low >> 8) ^ 
                         (word_hi & 0xFF) ^ (word_hi >> 8)); 
 
  IncWriteOut(0x03); 
  SendResponse(ack); 
} 
 
// ================================================================== 
 
void FormatResponse_Status(uint8_t ack) { 
 
  IncWriteOut(0x02); 
  IncWriteOut(0x08); 
  IncWriteOut(0xFD); 
  IncWriteOut(ack); 
 
  IncWriteOut(READER_RELEASE); 
  IncWriteOut(READER_DATE | ((READER_MONTH & 0x07) << 5)); 
  IncWriteOut((READER_MONTH >> 3) | (READER_YEAR << 1)); 
 
  IncWriteOut(READER_FAMILY);   //Read Only firmware 
  IncWriteOut(0x08 ^ 0xFD ^ ack ^ READER_RELEASE ^ (READER_DATE | ((READER_MONTH & 0x07) << 5)) ^ ((READER_MONTH >> 3) | (READER_YEAR << 1)) ^ READER_FAMILY); 
 
  IncWriteOut(0x03); 
  SendResponse(ack); 
} 
 
// ================================================================== 
 
void FormatResponse_AutoDefaultRead(uint8_t ack, uint8_t cmd, uint8_t type, uint32_t byte, uint32_t word) { 
 
  uint8_t checksum = 0, i; 
 
  IncWriteOut(0x02); 
  IncWriteOut(0x0A); 
  IncWriteOut(cmd); 
  IncWriteOut(ack); 
  IncWriteOut(type); 
  IncWriteOut(byte); 
  checksum = 0x0A ^ cmd ^ ack ^ type ^ byte; 
 
  for(i=0;i<4;i++) { 
    IncWriteOut(word >> 24); 
    checksum ^= word >> 24; 
    word <<= 8; 
  } 
 
  IncWriteOut(checksum); 
  IncWriteOut(0x03); 
  SendResponse(ack); 
}