📄 level2.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 + -