📄 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 <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <stdio.h>
#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<<FE)|(1<<DOR)|(1<<PE))) != 0) { //frame error, data overrun or parity error
uart_in_error = 1; //set flag in error
};
}
// ==================================================================
// uart byte transmission
SIGNAL(SIG_UART_DATA)
{
if (uart_out_end != uart_out_read) { //if current message is being sent
UDR = uart_out_buffer[uart_out_read++]; //send next byte
if (uart_out_read == UART_OUT_BUFFER_SIZE)
uart_out_read = 0;
} else {
cbi(UCSRB, UDRIE); //else stop
}
}
// ==================================================================
// uart init routine
void UARTIni(void) {
// UCSRA is not necessary to set up, using initial valuses
// no double transmission speed, no multi-processor mode
UCSRB = (1<<RXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN);
// set up : RXCIE, UDRIE, RXEN, TXEN
// (interrupt enable from receiver,
// UART receiver enable, UART transmit enable)
UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
// asynchronous operation, 8 data bits,
// no parity, 1 stop bit
UBRRL = 103; // baud rate - see UBRR register setting table
// in AVR ATmega8 specification
// UBRRH - using initial values
// UBRRL - 51 for frequency f=8 MHz
// - 103 for frequency f=16 MHz
// (using SINGLE transmission speed)
uart_in_read = uart_in_write = uart_in_end = 0;
uart_out_read = uart_out_write = uart_out_end = 0;
uart_state = UART_EMPTY;
}
// ==================================================================
// increase uart_out_write pointer by 1
// (to consider which one has better space/speed trade-off)
void IncWriteOut(uint8_t x) {
uart_out_buffer[uart_out_write++] = x;
if (uart_out_write == UART_OUT_BUFFER_SIZE)
uart_out_write = 0;
}
// ==================================================================
// parsing procedures
// ==================================================================
// ==================================================================
// checks pending bytes in uart buffer to find known message format
// if already received bytes form incomplete known message, UART_MESSAGE_OK is returned
// if any chaos bytes are detected, appropriate error is returned
// if complete known message is detected and parsed ok, command type is returned,
// uart_read_msg_bytes size is set and command respective values are parsed
uint8_t CheckIncommingMessage(void) {
uint8_t ptr = uart_in_read;
uint8_t result = UART_MESSAGE_OK;
uint8_t c;
if (uart_in_overflow != 0) {
uart_in_overflow = 0; //buffer is dropped
uart_in_read = uart_in_write; //=async
return ERR_UART_OVERFLOW;
}
if (uart_in_error != 0) {
uart_in_error = 0; //buffer is dropped
uart_in_read = uart_in_write; //=async
return ERR_UART_ERROR_FLAG;
}
if (uart_in_read == uart_in_write) {
return UART_MESSAGE_OK;
}
uart_state = UART_EMPTY;
result = UART_MESSAGE_OK;
while ((ptr != uart_in_write) && (uart_state != UART_WAIT_ERROR_SENT) && (uart_state != UART_VALID)) {
c = uart_in_buffer[ptr];
//positive branches inside each case are usually written first
switch (uart_state) {
case UART_EMPTY : //detect STX
if (c == 0x00) { //zero byte is ignored
} else
if (c == 0x02) {
uart_state = UART_READ_SIZE;
} else {
uart_state = UART_WAIT_ERROR_SENT;
result = ERR_UART_ERROR_FLAG;
}
break;
case UART_READ_SIZE : //capture size byte
if ((c >= 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -