📄 level2.c
字号:
#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include "level4.h"
#include "level3.h"
#include "level2.h"
#include "level1.h"
//--------------------------------------------------------------
//global variables
uint8_t bufferClean = 0; //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
#ifdef DEBUG
uint16_t solich = 0;
uint16_t offset = 0;
#endif
//uint16_t fwd_delays[7] = { -81, -238, -384, -531, -685, -831, -975 }; //for 16MHz clock
uint16_t fwd_delays[ 7 ] = { -81, -238, -384, -533, -687, -833, -977 }; //for 16MHz clock
uint16_t fwd_flow[ 9 ];
//--------------------------------------------------------------
//local variables
register uint8_t captured_byte asm ("r6"); //store_bit current capture bits
register uint8_t captured_valid asm ("r7"); //store_bit current capture valid bits
register uint8_t capture_cnt asm ("r8"); //store_bit current capture byte index
register uint8_t captured_bit_count asm ("r9"); //store_bit current capture bit counter
#define SPI_DELAY 5 //dummy cycles of WaitSPI
volatile uint8_t fwd_bit_phase; //forwardlink bit phase
uint8_t fwd_bit_sz; //forwardlink bit counter
uint8_t * fwd_write_ptr; //forwardlink bit pointer
uint8_t field_stop; //next field stop in RF clocks
// ==================================================================
// Forward link interrupt routine (implements a final state machine)
SIGNAL ( SIG_OVERFLOW1 )
{
if ( forward_link_type == 0x01 ) //1 from 4 type forwardlink
{
switch ( fwd_bit_phase )
{
case 4 :
cbi( PORTC , MOD_PIN );
if ( fwd_bit_sz-- > 0 )
{ //prepare next bit modulation
TCNT1 = fwd_delays[ ( *fwd_write_ptr ) * 2 ];
fwd_bit_phase = 5;
}
else
{ //EOF
TCNT1 = fwd_delays[ 1 ];
fwd_bit_phase = 8;
}
break;
case 5:
sbi( PORTC , MOD_PIN );
TCNT1 = fwd_delays[ 0 ];
if ( ( *fwd_write_ptr ) == 3 )
{
fwd_write_ptr++;
fwd_bit_phase = 4;
}
else
fwd_bit_phase = 6;
break;
case 6:
cbi( PORTC , MOD_PIN );
TCNT1 = fwd_delays[ 5 - ( ( *fwd_write_ptr++ ) * 2 ) ];
fwd_bit_phase = 4;
break;
case 12: //standalone EOF
sbi( PORTC , MOD_PIN );
TCNT1 = fwd_delays[ 0 ];
fwd_bit_phase = 13;
break;
case 13:
cbi( PORTC , MOD_PIN );
TCNT1 = -755;
fwd_bit_phase = 5; //generate 2nd standalone EOF pulse
break;
default :
if ( fwd_bit_phase < 9 )
{
TCNT1 = fwd_flow[ fwd_bit_phase ];
if ( fwd_bit_phase & 1 )
cbi( PORTC , MOD_PIN );
else
sbi( PORTC , MOD_PIN );
fwd_bit_phase++;
}
else
{
TCCR1B = 0; //no clock T1
cbi( PORTC , MOD_PIN );
cbi( TIMSK , TOIE1 ); //stop
cbi( TIFR , TOV1 ); //clear pending int
}
break;
}
}
else
{ //invalid modulation type
TCCR1B = 0; //no clock T1
cbi( TIMSK , TOIE1 ); //else stop
cbi( TIFR , TOV1 ); //clear pending int
}
}
// ==================================================================
// Forward Link setup function
// Requires: forwarLink_data filled with valid bits (1 bit per byte)
// fwd_bit_count set with number of bits to be sent
void SendForward( uint8_t fwd_bit_count )
{
fwd_write_ptr = data_buffer;
fwd_bit_sz = fwd_bit_count;
fwd_bit_phase = 0;
int i;
for ( i = 0 ; i < 9 ; i++ )
fwd_flow[ i ] = fwd_delays[ 0 ];
fwd_flow[ 1 ] = fwd_delays[ 3 ];
fwd_flow[ 3 ] = fwd_delays[ 1 ];
TCNT1 = -256; //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 )
{
// SetLEDOff();
// SetLEDOn();
// SetLEDOff();
}
}
// ==================================================================
// prepares data bit pairs
// see EM4x35 uplink spec
uint8_t Prepare_Data( uint8_t data )
{
register uint8_t i;
for ( i = 0 ; i < 4 ; i++ )
{
*forward_ptr++ = data & 3;
data >>= 2;
}
return 4; //return number of emited bits
}
// ==================================================================
void ClearCaptureBuffers( void )
{
uint8_t i;
for ( i = 0 ; i < CAPTURE_SIZE ; i++ )
{
capture.capture_data[ i ] = 0;
capture.capture_valid[ i ] = 0xFF;
}
bufferClean = 1;
}
// ==================================================================
void WaitSPI(void) {
int register x = SPI_DELAY;
while(x-->0)
{}
}
// ==================================================================
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);
}
// ==================================================================
uint16_t CRC( uint8_t * data , uint8_t len )
{
uint16_t crc = 0xFFFF; //CRC preset
uint8_t i , j , feedback;
#define crc_poly 0x8408 //CRC polynom
for ( i = 0 ; i < len ; i++ )
{
crc ^= *data++;
for ( j = 0 ; j < 8 ; j++ )
{
feedback = crc & 1;
crc >>= 1;
if ( feedback )
crc ^= crc_poly;
}
}
return ~crc;
}
// ==================================================================
// Search 1st valid bit ('1' from SOF)
// maximum size bits to be searched from start position to end position
//
// ASK data usually starts at bit position 0 or 1 of captured_data
// FSK data usually starts at 4th bit position
uint8_t SearchValidBit( uint8_t start , uint8_t end )
{
uint8_t bitcnt = start % 8;
uint8_t byte = start / 8;
uint8_t valid;
uint8_t *ptr = capture.capture_valid + start / 8;
if ( ( decode_number & 1 ) == 0 ) //ASK specific
{
while ( start < end )
{
valid = ( ( *ptr ) >> ( 7 - bitcnt ) ) & 1;
if ( valid == 0 )
return start; //return 1st valid bit position
if ( ++bitcnt > 7 )
{
bitcnt = 0;
ptr++;
}
start++;
}
}
else
{ //FSK specific
valid = capture.capture_data[ byte ];
byte = valid & 0xF0;
if ( byte == 0x50 )
if ( ( ( *ptr ) & 0xF0 ) == 0 )
return 3;
byte = valid & 0x78;
if ( byte == 0x28 )
if ( ( ( *ptr ) & 0x78 ) == 0 )
return 4;
}
return 255; //no valid bit
}
// ==================================================================
// Extracts decoded data to bytes accroding to start position
// valid start range is < 255
uint8_t ExtractData( uint8_t size )
{
uint8_t value = 0;
uint8_t valid;
uint8_t pom;
uint8_t start;
uint8_t bitcnt;
uint8_t ptr = 0;
uint8_t running_one;
pom = SearchValidBit( 0 , 7 ); //find the first valid bit in 0th byte of capture_valid
if ( pom == 255 )
return size;
start = pom;
bitcnt = start % 8; //set the pointers
start = start / 8;
running_one = 1 << ( 7 - bitcnt );
pom = capture.capture_data[ start ] & running_one; //check the 1st bit is '1'
if ( pom == 0 )
return size;
while ( size > 0 )
{
if ( bitcnt == 7 ) //increment position to next bit
{
bitcnt = 0;
running_one = 0x80;
start++;
}
else
{
bitcnt++;
running_one >>= 1;
}
pom = capture.capture_data[ start ] & running_one;
value >>= 1;
if ( pom != 0 )
value |= 0x80;
valid = capture.capture_valid[ start ] & running_one;
if ( valid != 0 )
break;
size--;
data_buffer[ ptr / 8 ] = value >> ( 7 - ( ptr & 7 ) ); //always store the byte (for inventory)
ptr++;
}
return size;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -