⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 level2.c

📁 此程序为利用mage8 AVR 和EM4094实现读取TYPE A类型卡的C程序、读卡稳定、这个项目我们做了好久、非常不错的程序、很适合做这方面产品的朋友们参考
💻 C
字号:


#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/wdt.h>
#include "level4.h"
#include "level3.h"
#include "level2.h"
#include "level1.h"

//--------------------------------------------------------------
//global variables

uint8_t bufferClean;                         //flag for pre-cleaning
struct TCAPTURE capture;
uint8_t * forward_ptr;                       //ptr for forward message preparation
uint8_t data_buffer[ CAPTURE_SIZE ];           //array of forwarded bits XOR clean response data
uint16_t fwd_A_timing[ 4 ] = { -30 , -108 , -183 , -257 };                    //forward link pulse timing
#define SPI_DELAY 5                          //dummy cycles of WaitSPI 
uint8_t * fwd_write_ptr;                     //forwardlink bit pointer
uint16_t fwd_current_timing;                 //next field change in RF clocks
uint8_t fwd_this_bit;                        //this bit

//aliases
#define fwd_bit_sz captured_byte
#define fwd_byte_bit_cnt captured_valid
#define fwd_byte captured_bit_count

//--------------------------------------------------------------
//local declaration
void ClearCaptureBuffers( void );
uint8_t ExtractTypeAData( uint8_t size );
uint16_t ISOCRCA( uint8_t *data , uint8_t len );
uint8_t Prepare_Data( uint8_t data , uint8_t msg_size );
uint8_t Prepare_EOF( uint8_t msg_size );
uint8_t Prepare_SOF( void );
uint8_t SearchValidBit( uint8_t start , uint8_t end );
void SendForward( uint8_t fwd_bit_count );
void ShiftFwdData( uint8_t data , uint8_t cnt );
void WaitSPI( void );
void WriteSPI( uint16_t low , uint16_t hi );


// ********************************************************************************************
// Description : Send modified Milea code to EM4094 DIN routine .
// Return value: None   
// parameter   : 
// ********************************************************************************************

SIGNAL ( SIG_OVERFLOW1 ) 
{
    if ( fwd_bit_sz-- == 0 )              //prepare next byte modulation
    {                 
        TCCR1B = 0;                       //no clock T1
        cbi( TIMSK , TOIE1 );             //stop 
        cbi( TIFR  ,  TOV1 );             //clear pending int
        return;
    }
    TCNT1 = fwd_current_timing;
    uint8_t k;
    for ( k = 0 ; k < 6 ; k++ ) 
    {
        sbi( PORTC , MOD_PIN );           //mod pulse
    }    
    cbi( PORTC , MOD_PIN );
//////////////////////////////prepare the next period timing
    if ( fwd_this_bit == 0 ) 
    {
        if ( fwd_byte & 1 ) 
        {
            k = 2;                        //between (not the last)zero and 1
        } 
        else 
        {                                   
            k = 1;                        //between (not the first) two zeros
        }

    } 
    else 
    {
        if ( fwd_byte & 1 ) 
        {                          
            k = 1;                        //between two ones
        } 
        else 
        {
            fwd_byte >>= 1;               //the first zero is skipped
            if ( --fwd_byte_bit_cnt == 0 ) 
            {
                fwd_byte_bit_cnt = 8;
                fwd_byte = *fwd_write_ptr++;
            }

            if ( fwd_bit_sz-- == 0 ) 
            {                  
                TCCR1B = 0;               //no clock T1
                cbi( TIMSK , TOIE1 );     //stop 
                cbi( TIFR , TOV1 );       //clear pending int
                return;
            }
            if ( fwd_byte & 1 ) 
            {                       
                k = 3;                    //between the one and the one with zero in between
            } 
            else 
            {
                k = 2;                    //between the one and the second zero
            }
        }
    } 
    fwd_current_timing = fwd_A_timing[ k ]; 
    fwd_this_bit = fwd_byte & 1;
    fwd_byte >>= 1;                       //the first zero is skipped
    if ( --fwd_byte_bit_cnt == 0 ) 
    {
        fwd_byte_bit_cnt = 8;
        fwd_byte = *fwd_write_ptr++;
    }
}

// ********************************************************************************************
// Description : Start to send modified Milla code to EM4094 DIN.
// Return value: None.   
// parameter   : fwd_bit_count -- the number of the bit to be sent.
// ********************************************************************************************

void SendForward( uint8_t fwd_bit_count ) 
{
    fwd_write_ptr = data_buffer;
    fwd_byte = *fwd_write_ptr++;
    fwd_byte_bit_cnt = 8;
    fwd_bit_sz = fwd_bit_count;
    fwd_bit_sz++;                                 //add 1 bit for EOF
    if ( fwd_bit_count > 8 ) 
    {
      fwd_bit_sz++;
    }
    fwd_this_bit = fwd_byte & 1;
    fwd_byte >>= 1;
    fwd_byte_bit_cnt--;

    if ( fwd_this_bit ) 
        fwd_current_timing = fwd_A_timing[ 2 ];
    else
        fwd_current_timing = fwd_A_timing[ 1 ];
    TCNT1 = -316;                            //minimum startup pulse length
    cbi( PORTC , MOD_PIN );                   //notmod pulse
    sbi(TIMSK, TOIE1);
    TCCR1B = 1;                              //internal clock T1, RUN!
    // waiting for clearing TOIE1 => command sending
    while ( bit_is_set( TIMSK , TOIE1 ) != 0 )
    {}
    cbi( PORTC , MOD_PIN );                   //notmod pulse
}

// ********************************************************************************************
// Description : To realize the LSB to be sent first.
// Return value: 16 bit binary.   
// parameter   : data -- the btye to be sent;
//               cnt  -- the number of bit to be sent in data.
// ********************************************************************************************

void ShiftFwdData( uint8_t data , uint8_t cnt ) 
{
    uint8_t i;

    for ( i = 0 ; i < cnt ; i++ ) 
    {
        fwd_byte |= ( data & 1 ) << fwd_byte_bit_cnt++;
        data >>= 1;
        if ( fwd_byte_bit_cnt == 8 ) 
        {
            *forward_ptr++ = fwd_byte;
            fwd_byte_bit_cnt = 0;
            fwd_byte = 0;
        }
    }
    *forward_ptr = fwd_byte;             //store in all cases
}


// ********************************************************************************************
// Description : Prepare SOF of the Type A data before a frame.
// Return value:    
// parameter   : 
// ********************************************************************************************

uint8_t Prepare_SOF( void ) 
{
    forward_ptr = data_buffer;
    fwd_byte = 0;
    fwd_byte_bit_cnt = 0;
    return 0;                               //return number of emited bits
}

// ********************************************************************************************
// Description : Prepare the data bit to be send to EM4094 DIN.
// Return value:    
// parameter   : 
// ********************************************************************************************

uint8_t Prepare_Data( uint8_t data , uint8_t msg_size )  //Type A
{
    uint8_t i , j = 8;
    
    ShiftFwdData( data , j );
    
    if ( msg_size > 1 ) 
    {
        i = 1;
        for ( ; j > 0 ; j-- ) 
        {
            i ^= data;
            data >>= 1;
        }
        ShiftFwdData( i , 1 );
        j = 9;
    }
    return j;
}

// ********************************************************************************************
// Description : Prepare EOF of type A .
// Return value:   
// parameter   : 
// ********************************************************************************************

uint8_t Prepare_EOF( uint8_t msg_size ) 
{
    if ( forward_link_type == 0x02 ) 
    {
        if ( msg_size > 1 )
        ShiftFwdData( 0 , 1 );      
    }
    return 0;
}

// ********************************************************************************************
// Description : Clear all data in capture.decoded_data structure.
// Return value: None.   
// parameter   : None.
// ********************************************************************************************

void ClearCaptureBuffers( void ) 
{
    uint8_t i;
    for( i = 0 ; i < CAPTURE_SIZE ; i++ ) 
    {
        capture.decoded_data.capture_data[ i ]  = 0;
        capture.decoded_data.capture_valid[ i ] = 0xFF;
    }
    
    bufferClean = 1;
}


// ********************************************************************************************
// Description : Delay some time in configure EM4094 routine(WriteSPI()).
// Return value: None.   
// parameter   : None.
// ********************************************************************************************

void WaitSPI( void ) 
{
    int register x = SPI_DELAY;
    while( x-- > 0 )
    {}
}

// ********************************************************************************************
// Description : Configure the EM4094 31 option bit.
// Return value: None.   
// parameter   : low -- the low 16 bit value of 32 bit option;
//               hi  -- the high 16 bit value of 32 bit option.
// ********************************************************************************************

void WriteSPI( uint16_t low , uint16_t hi ) 
{
    int16_t data   = low;  
    uint8_t bitcnt = 32;  

    //SPI start event
    cbi( PORTC , MOD_PIN );
    WaitSPI( );
    sbi( PORTC , DCLK_PIN );
    WaitSPI( );
    sbi( PORTC , MOD_PIN );
    WaitSPI( );

    while ( bitcnt-- > 0 ) 
    {
        cbi( PORTC , DCLK_PIN );
        WaitSPI( );
        if ( data & 1 ) 
        	  sbi( PORTC , MOD_PIN ); 
        else 
        	  cbi( PORTC , MOD_PIN );
        WaitSPI( );
        data >>= 1;
        if ( bitcnt == 16 )
            data = hi;
        sbi( PORTC , DCLK_PIN );
        WaitSPI( );
    }
    cbi( PORTC , DCLK_PIN );              //for the first time, DCLK is '1', for the next, enable DIN
    WaitSPI( );
    cbi( PORTC , MOD_PIN );
}

// ********************************************************************************************
// Description : Extracts decoded data of type A from capture.decoded_data to data_buffer 
//               in bytes.
// Return value: 16 bit binary.   
// parameter   : *data -- the point of the start data to be checked;
//               len   -- the number of data to be checked;
// ********************************************************************************************
uint16_t ISOCRCA( uint8_t *data , uint8_t len ) 
{
    uint16_t crc = 0x6363;        //CRC preset
    uint8_t i, j;
    const uint16_t poly = 0x8408; //CRC polynom

    for ( i = 0 ; i < len ; i++ ) 
    {
        crc ^= data[ i ];
        for ( j = 0 ; j < 8 ; j++ )
        {
            if ( crc & 1 ) 
            	  crc = ( crc >> 1 ) ^ poly;
            else 
            	  crc = ( crc >> 1 );
        }
    }
    return crc;
}

// ********************************************************************************************
// Description :Search the first valid data position in capture.decoded_data from start to end.
// Return      :
// Parameter   : 
// ********************************************************************************************

uint8_t SearchValidBit( uint8_t start , uint8_t end ) 
{
    uint8_t bitcnt = start % 8;
    uint8_t byte = start / 8;
    uint8_t valid;

    while ( start < end ) 
    {
       valid = ( capture.decoded_data.capture_valid[ byte ] >> ( 7 - bitcnt ) ) & 1;
       if ( valid == 0 ) //return 1st valid bit position
       	   return start; 
       if ( bitcnt == 7 ) 
       {
           bitcnt = 0;
           byte++;
       } 
       else
           bitcnt++;
       start++;
    }
    return 255;                               //no valid bit
}



// ********************************************************************************************
// Extracts decoded data of type A from capture.decoded_data to data_buffer in bytes. 
// ********************************************************************************************

uint8_t ExtractTypeAData( uint8_t size ) 
{
    uint8_t value = 0;
    uint8_t valid;
    uint8_t pom;  
    uint8_t phase;  
    uint8_t phase_position;  
    uint8_t start;
    uint8_t bitcnt;
    uint8_t ptr = 0;
    uint8_t parity = 0;

    pom = SearchValidBit( 0 , 7 );             //find the first valid bit in 0th byte of capture_valid
    if ( pom == 255 ) 
    	  return 0;
    start = pom;
    bitcnt = start % 8;                                             //set the pointers
    start = start / 8;
    phase = phase_position = 0;

    while ( size > 0 ) 
    {
        pom = ( capture.decoded_data.capture_data[ start ] >> ( 7 - bitcnt ) ) & 1;
        value >>= 1;
        if ( pom != 0 )
        	  value |= 0x80;      
        valid = ( capture.decoded_data.capture_valid[ start ] >> ( 7 - bitcnt ) ) & 1;
        if( valid != 0 )
            break;
        if ( bitcnt == 7 ) 
        {                                           //increment position to next bit
            bitcnt = 0;
            start++;
        } 
        else
            bitcnt++;
        size--;
        parity ^= pom;
        if ( phase == 0 ) 
        {                                            //SOF check
            if ( pom == 0 ) break;                           //1st bit should be '1'
            phase = 1;
            phase_position = 0;
            parity = 0;
        } 
        else if ( phase == 1 ) 
        {                                //shifting the data bits
            phase_position++;
            data_buffer[ ptr / 8 ] = value;                    //always store the byte for debug purposes
            if ( phase_position == 8 ) 
            {                     //is 8 bits shifted
                phase = 2;
            } 
            else 
            {
                ptr++;
            }
        } 
        else if ( phase == 2 ) 
        {                                //check the parity
            if ( ( parity & 1 ) == 0 ) 
            {
                return ptr;                                 //force parity error
            }
            ptr++;
            phase = 1;
            phase_position = 0;
            parity = 0;
        }
    }
    return ptr;
}

///***********************************************************************************
///***********************************************************************************

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -