Merge pull request #37 from ceres-c/rrg-iso15693-codec-upd

Porting ISO15693 codec and applications updates
This commit is contained in:
Iceman
2020-09-13 00:50:25 +02:00
committed by GitHub
22 changed files with 3926 additions and 3841 deletions
+62 -54
View File
@@ -23,9 +23,6 @@ static enum {
} State;
bool loggedIn;
uint8_t MyAFI; /* This variable holds current tag's AFI (is used in inventory) */
CurrentFrame FrameInfo;
void EM4233AppInit(void) {
State = STATE_READY;
@@ -38,7 +35,7 @@ void EM4233AppInit(void) {
FrameInfo.Selected = false;
loggedIn = false;
MemoryReadBlock(&MyAFI, EM4233_MEM_AFI_ADDRESS, 1);
MemoryReadBlock(&Uid, EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
}
void EM4233AppReset(void) {
@@ -51,6 +48,8 @@ void EM4233AppReset(void) {
FrameInfo.Addressed = false;
FrameInfo.Selected = false;
loggedIn = false;
MemoryReadBlock(&MyAFI, EM4233_MEM_AFI_ADDRESS, 1);
MemoryReadBlock(&Uid, EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
}
void EM4233AppTask(void) {
@@ -62,7 +61,7 @@ void EM4233AppTick(void) {
}
uint16_t EM4233_Lock_Block(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t BlockAddress = *FrameInfo.Parameters;
uint8_t LockStatus = 0;
@@ -92,7 +91,7 @@ uint16_t EM4233_Lock_Block(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Write_Single(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t BlockAddress = *FrameInfo.Parameters;
uint8_t *Dataptr = FrameInfo.Parameters + 0x01; /* Data to write begins on 2nd byte of the frame received by the reader */
uint8_t LockStatus = 0;
@@ -127,7 +126,7 @@ uint16_t EM4233_Write_Single(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Read_Single(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t FramePtr; /* holds the address where block's data will be put */
uint8_t BlockAddress = FrameInfo.Parameters[0];
uint8_t LockStatus = 0;
@@ -138,7 +137,7 @@ uint16_t EM4233_Read_Single(uint8_t *FrameBuf, uint16_t FrameBytes) {
if (BlockAddress >= EM4233_NUMBER_OF_BLCKS) { /* check if the reader is requesting a sector out of bound */
if (FrameInfo.Addressed) { /* If the request is addressed */
FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR;
FrameBuf[ISO15693_RES_ADDR_PARAM] = 0x0F; /* Magic number from real tag */
FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_GENERIC;
ResponseByteCount += 2; /* Copied this behaviour from real tag, not specified in ISO documents */
}
return ResponseByteCount; /* If not addressed real tag does not respond */
@@ -168,7 +167,7 @@ uint16_t EM4233_Read_Single(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Read_Multiple(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t FramePtr; /* holds the address where block's data will be put */
uint8_t BlockAddress = FrameInfo.Parameters[0];
uint8_t BlocksNumber = FrameInfo.Parameters[1] + 0x01; /* according to ISO standard, we have to read 0x08 blocks if we get 0x07 in request */
@@ -179,7 +178,7 @@ uint16_t EM4233_Read_Multiple(uint8_t *FrameBuf, uint16_t FrameBytes) {
if (BlockAddress >= EM4233_NUMBER_OF_BLCKS) { /* the reader is requesting a block out of bound */
if (FrameInfo.Addressed) { /* If the request is addressed */
FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR;
FrameBuf[ISO15693_RES_ADDR_PARAM] = 0x0F; /* Magic number from real tag */
FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_GENERIC;
ResponseByteCount += 2; /* Copied this behaviour from real tag, not specified in ISO documents */
}
return ResponseByteCount; /* If not addressed real tag does not respond */
@@ -224,7 +223,7 @@ uint16_t EM4233_Read_Multiple(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Write_AFI(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t AFI = FrameInfo.Parameters[0];
uint8_t LockStatus = 0;
@@ -251,7 +250,7 @@ uint16_t EM4233_Write_AFI(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Lock_AFI(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t LockStatus = 0;
if (FrameInfo.ParamLen != 0)
@@ -278,7 +277,7 @@ uint16_t EM4233_Lock_AFI(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Write_DSFID(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t DSFID = FrameInfo.Parameters[0];
uint8_t LockStatus = 0;
@@ -304,7 +303,7 @@ uint16_t EM4233_Write_DSFID(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Lock_DSFID(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t LockStatus = 0;
if (FrameInfo.ParamLen != 0)
@@ -331,7 +330,7 @@ uint16_t EM4233_Lock_DSFID(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint8_t EM4233_Get_SysInfo(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t FramePtr; /* holds the address where block's data will be put */
if (FrameInfo.ParamLen != 0)
@@ -354,8 +353,6 @@ uint8_t EM4233_Get_SysInfo(uint8_t *FrameBuf, uint16_t FrameBytes) {
ResponseByteCount += 1; /* Increment the response count */
/* Then append UID */
uint8_t Uid[ActiveConfiguration.UidSize];
EM4233GetUid(Uid);
ISO15693CopyUid(&FrameBuf[FramePtr], Uid);
FramePtr += ISO15693_GENERIC_UID_SIZE; /* Move forward the buffer data pointer */
ResponseByteCount += ISO15693_GENERIC_UID_SIZE; /* Increment the response count */
@@ -398,7 +395,7 @@ uint8_t EM4233_Get_SysInfo(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Get_Multi_Block_Sec_Stat(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t FramePtr; /* holds the address where block's data will be put */
uint8_t BlockAddress = FrameInfo.Parameters[0];
uint8_t BlocksNumber = FrameInfo.Parameters[1] + 0x01;
@@ -427,7 +424,7 @@ uint16_t EM4233_Get_Multi_Block_Sec_Stat(uint8_t *FrameBuf, uint16_t FrameBytes)
}
uint16_t EM4233_Select(uint8_t *FrameBuf, uint16_t FrameBytes, uint8_t *Uid) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
/* I've no idea how this request could generate errors ._.
if ( ) {
FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR;
@@ -463,7 +460,7 @@ uint16_t EM4233_Select(uint8_t *FrameBuf, uint16_t FrameBytes, uint8_t *Uid) {
}
uint16_t EM4233_Reset_To_Ready(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
/* I've no idea how this request could generate errors ._.
if ( ) {
FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR;
@@ -487,7 +484,7 @@ uint16_t EM4233_Reset_To_Ready(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Login(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t Password[4] = { 0 };
if (FrameInfo.ParamLen != 4 || !FrameInfo.Addressed || !(FrameInfo.Selected && State == STATE_SELECTED))
@@ -523,7 +520,7 @@ uint16_t EM4233_Login(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Auth1(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
// uint8_t KeyNo = *FrameInfo.Parameters; /* Right now this parameter is unused, but it will be useful */
if (FrameInfo.ParamLen != 1) /* Malformed: not enough or too much data */
@@ -548,7 +545,7 @@ uint16_t EM4233_Auth1(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Auth2(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
// uint8_t A2 = FrameInfo.Parameters;
// uint8_t f = FrameInfo.Parameters + 0x08;
// uint8_t g[3] = { 0 }; /* Names according to EM Marin definitions */
@@ -566,9 +563,7 @@ uint16_t EM4233_Auth2(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233AppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t Uid[ActiveConfiguration.UidSize];
EM4233GetUid(Uid);
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
if ((FrameBytes < ISO15693_MIN_FRAME_SIZE) || !ISO15693CheckCRC(FrameBuf, FrameBytes - ISO15693_CRC16_SIZE))
/* malformed frame */
@@ -585,8 +580,8 @@ uint16_t EM4233AppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
return ISO15693_APP_NO_RESPONSE;
if (State == STATE_READY || State == STATE_SELECTED) {
if (*FrameInfo.Command == ISO15693_CMD_INVENTORY) {
switch (*FrameInfo.Command) {
case ISO15693_CMD_INVENTORY:
if (FrameInfo.ParamLen == 0)
return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */
@@ -596,59 +591,77 @@ uint16_t EM4233AppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
ISO15693CopyUid(&FrameBuf[ISO15693_RES_ADDR_PARAM + 0x01], Uid);
ResponseByteCount += 10;
}
break;
} else if ((*FrameInfo.Command == ISO15693_CMD_STAY_QUIET) && FrameInfo.Addressed) {
State = STATE_QUIET;
case ISO15693_CMD_STAY_QUIET:
if (FrameInfo.Addressed)
State = STATE_QUIET;
break;
} else if (*FrameInfo.Command == ISO15693_CMD_READ_SINGLE) {
case ISO15693_CMD_READ_SINGLE:
ResponseByteCount = EM4233_Read_Single(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_WRITE_SINGLE) {
case ISO15693_CMD_WRITE_SINGLE:
ResponseByteCount = EM4233_Write_Single(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_LOCK_BLOCK) {
case ISO15693_CMD_LOCK_BLOCK:
ResponseByteCount = EM4233_Lock_Block(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_READ_MULTIPLE) {
case ISO15693_CMD_READ_MULTIPLE:
ResponseByteCount = EM4233_Read_Multiple(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_WRITE_AFI) {
case ISO15693_CMD_WRITE_AFI:
ResponseByteCount = EM4233_Write_AFI(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_LOCK_AFI) {
case ISO15693_CMD_LOCK_AFI:
ResponseByteCount = EM4233_Lock_AFI(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_WRITE_DSFID) {
case ISO15693_CMD_WRITE_DSFID:
ResponseByteCount = EM4233_Write_DSFID(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_LOCK_DSFID) {
case ISO15693_CMD_LOCK_DSFID:
ResponseByteCount = EM4233_Lock_DSFID(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_GET_SYS_INFO) {
case ISO15693_CMD_GET_SYS_INFO:
ResponseByteCount = EM4233_Get_SysInfo(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_GET_BLOCK_SEC) {
case ISO15693_CMD_GET_BLOCK_SEC:
ResponseByteCount = EM4233_Get_Multi_Block_Sec_Stat(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_RESET_TO_READY) {
case ISO15693_CMD_RESET_TO_READY:
ResponseByteCount = EM4233_Reset_To_Ready(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == EM4233_CMD_LOGIN) {
case EM4233_CMD_LOGIN:
ResponseByteCount = EM4233_Login(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == EM4233_CMD_AUTH1) {
case EM4233_CMD_AUTH1:
ResponseByteCount = EM4233_Auth1(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == EM4233_CMD_AUTH2) {
case EM4233_CMD_AUTH2:
ResponseByteCount = EM4233_Auth2(FrameBuf, FrameBytes);
break;
} else {
default:
if (FrameInfo.Addressed) {
FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR;
FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_NOT_SUPP;
ResponseByteCount = 2;
} /* EM4233 respond with error flag only to addressed commands */
}
break;
}
} else if (State == STATE_QUIET) {
if (*FrameInfo.Command == ISO15693_CMD_RESET_TO_READY) {
@@ -656,12 +669,6 @@ uint16_t EM4233AppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
}
if (ResponseByteCount > 0) {
/* There is data to send. Append CRC */
ISO15693AppendCRC(FrameBuf, ResponseByteCount);
ResponseByteCount += ISO15693_CRC16_SIZE;
}
return ResponseByteCount;
}
@@ -669,6 +676,7 @@ void EM4233GetUid(ConfigurationUidType Uid) {
MemoryReadBlock(&Uid[0], EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
}
void EM4233SetUid(ConfigurationUidType Uid) {
MemoryWriteBlock(Uid, EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
void EM4233SetUid(ConfigurationUidType NewUid) {
memcpy(Uid, NewUid, ActiveConfiguration.UidSize);
MemoryWriteBlock(NewUid, EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
}
@@ -2,6 +2,11 @@
#include "../Common.h"
#include <util/crc16.h>
CurrentFrame FrameInfo;
uint8_t Uid[ISO15693_GENERIC_UID_SIZE];
uint8_t MyAFI;
uint16_t ResponseByteCount;
//Refer to ISO/IEC 15693-3:2001 page 41
uint16_t calculateCRC(void *FrameBuf, uint16_t FrameBufSize) {
uint16_t reg = ISO15693_CRC16_PRESET;
@@ -85,6 +85,10 @@ typedef struct {
bool Addressed;
bool Selected;
} CurrentFrame;
extern CurrentFrame FrameInfo; /* Holds current frame information */
extern uint8_t Uid[];
extern uint8_t MyAFI; /* Holds current tag's AFI, used during inventory */
extern uint16_t ResponseByteCount; /* Length of response, used when building response frames */
void ISO15693AppendCRC(uint8_t *FrameBuf, uint16_t FrameBufSize);
bool ISO15693CheckCRC(void *FrameBuf, uint16_t FrameBufSize);
@@ -19,6 +19,9 @@
// TODO replace remaining magic numbers
uint8_t ReaderSendBuffer[CODEC_BUFFER_SIZE];
uint16_t ReaderSendBitCount;
static bool Selected = false;
Reader14443Command Reader14443CurrentCommand = Reader14443_Do_Nothing;
@@ -6,8 +6,8 @@
#define CRC_INIT 0x6363
uint8_t ReaderSendBuffer[CODEC_BUFFER_SIZE];
uint16_t ReaderSendBitCount;
extern uint8_t ReaderSendBuffer[];
extern uint16_t ReaderSendBitCount;
void Reader14443AAppInit(void);
void Reader14443AAppReset(void);
@@ -141,12 +141,6 @@ uint16_t Sl2s2002AppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
break;
}
if (ResponseByteCount > 0) {
/* There is data to be sent. Append CRC */
ISO15693AppendCRC(FrameBuf, ResponseByteCount);
ResponseByteCount += ISO15693_CRC16_SIZE;
}
return ResponseByteCount;
} else { // Invalid CRC
@@ -16,10 +16,8 @@ static enum {
STATE_QUIET
} State;
uint8_t MyAFI; /* Holds current tag's AFI (is used in inventory) */
uint16_t UserLockBits_Mask = 0; /* Holds lock state of blocks */
uint16_t FactoryLockBits_Mask = 0; /* Holds lock state of blocks */
CurrentFrame FrameInfo;
void TITagitstandardAppInit(void) {
State = STATE_READY;
@@ -35,6 +33,7 @@ void TITagitstandardAppInit(void) {
FrameInfo.Selected = false;
MemoryReadBlock(&MyAFI, TITAGIT_MEM_AFI_ADDRESS, 1);
TITagitstandardGetUid(Uid);
}
void TITagitstandardAppReset(void) {
@@ -46,6 +45,9 @@ void TITagitstandardAppReset(void) {
FrameInfo.ParamLen = 0;
FrameInfo.Addressed = false;
FrameInfo.Selected = false;
MemoryReadBlock(&MyAFI, TITAGIT_MEM_AFI_ADDRESS, 1);
TITagitstandardGetUid(Uid);
}
@@ -58,9 +60,7 @@ void TITagitstandardAppTick(void) {
}
uint16_t TITagitstandardAppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t Uid[ActiveConfiguration.UidSize];
TITagitstandardGetUid(Uid);
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
if ((FrameBytes < ISO15693_MIN_FRAME_SIZE) || !ISO15693CheckCRC(FrameBuf, FrameBytes - ISO15693_CRC16_SIZE))
/* malformed frame */
@@ -198,12 +198,6 @@ uint16_t TITagitstandardAppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
break;
}
if (ResponseByteCount > 0) {
/* There is data to be sent. Append CRC */
ISO15693AppendCRC(FrameBuf, ResponseByteCount);
ResponseByteCount += ISO15693_CRC16_SIZE;
}
return ResponseByteCount;
}
@@ -214,7 +208,8 @@ void TITagitstandardGetUid(ConfigurationUidType Uid) {
TITagitstandardFlipUid(Uid);
}
void TITagitstandardSetUid(ConfigurationUidType Uid) {
void TITagitstandardSetUid(ConfigurationUidType NewUid) {
memcpy(Uid, NewUid, ActiveConfiguration.UidSize); // Update the local variable
// Reverse UID before writing it
TITagitstandardFlipUid(Uid);
@@ -92,12 +92,6 @@ uint16_t VicinityAppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
break;
}
if (ResponseByteCount > 0) {
/* There is data to be sent. Append CRC */
ISO15693AppendCRC(FrameBuf, ResponseByteCount);
ResponseByteCount += ISO15693_CRC16_SIZE;
}
return ResponseByteCount;
} else { // Invalid CRC
+5
View File
@@ -24,6 +24,11 @@ static volatile struct {
uint8_t CodecBuffer[CODEC_BUFFER_SIZE];
uint8_t CodecBuffer2[CODEC_BUFFER_SIZE];
void (* volatile isr_func_CODEC_TIMER_LOADMOD_CCB_VECT)(void) = NULL;
void (* volatile isr_func_TCD0_CCC_vect)(void) = NULL;
void (* volatile isr_func_CODEC_DEMOD_IN_INT0_VECT)(void) = NULL;
// the following three functions prevent sending data directly after turning on the reader field
void CodecReaderFieldStart(void) { // DO NOT CALL THIS FUNCTION INSIDE APPLICATION!
if (!CodecGetReaderField() && !ReaderFieldFlags.ToBeRestarted) {
+28 -23
View File
@@ -8,26 +8,6 @@
#ifndef CODEC_H_
#define CODEC_H_
#include <avr/io.h>
#include <stdint.h>
#include <stdbool.h>
#include "../Common.h"
#include "../Configuration.h"
#include "../Settings.h"
#include "ISO14443-2A.h"
#include "Reader14443-2A.h"
#include "SniffISO14443-2A.h"
#include "ISO15693.h"
/* Timing definitions for ISO14443A */
#define ISO14443A_SUBCARRIER_DIVIDER 16
#define ISO14443A_BIT_GRID_CYCLES 128
#define ISO14443A_BIT_RATE_CYCLES 128
#define ISO14443A_FRAME_DELAY_PREV1 1236
#define ISO14443A_FRAME_DELAY_PREV0 1172
#define ISO14443A_RX_PENDING_TIMEOUT 4 // ms
/* Peripheral definitions */
#define CODEC_DEMOD_POWER_PORT PORTB
#define CODEC_DEMOD_POWER_MASK PIN0_bm
@@ -87,6 +67,27 @@
#define CODEC_TIMER_TIMESTAMPS_CCA_VECT TCD1_CCA_vect
#define CODEC_TIMER_TIMESTAMPS_CCB_VECT TCD1_CCB_vect
#ifndef __ASSEMBLER__
#include <avr/io.h>
#include <stdint.h>
#include <stdbool.h>
#include "../Common.h"
#include "../Configuration.h"
#include "../Settings.h"
#include "ISO14443-2A.h"
#include "Reader14443-2A.h"
#include "SniffISO14443-2A.h"
#include "ISO15693.h"
/* Timing definitions for ISO14443A */
#define ISO14443A_SUBCARRIER_DIVIDER 16
#define ISO14443A_BIT_GRID_CYCLES 128
#define ISO14443A_BIT_RATE_CYCLES 128
#define ISO14443A_FRAME_DELAY_PREV1 1236
#define ISO14443A_FRAME_DELAY_PREV0 1172
#define ISO14443A_RX_PENDING_TIMEOUT 4 // ms
#define CODEC_BUFFER_SIZE 256
@@ -115,13 +116,14 @@ typedef enum {
extern uint8_t CodecBuffer[CODEC_BUFFER_SIZE];
extern uint8_t CodecBuffer2[CODEC_BUFFER_SIZE];
void (* volatile isr_func_TCD0_CCC_vect)(void);
/* Shared ISR pointers and handlers */
extern void (* volatile isr_func_TCD0_CCC_vect)(void);
void isr_Reader14443_2A_TCD0_CCC_vect(void);
void isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT(void);
void (* volatile isr_func_CODEC_DEMOD_IN_INT0_VECT)(void);
extern void (* volatile isr_func_CODEC_DEMOD_IN_INT0_VECT)(void);
void isr_ISO14443_2A_TCD0_CCC_vect(void);
void isr_ISO15693_CODEC_DEMOD_IN_INT0_VECT(void);
void (* volatile isr_func_CODEC_TIMER_LOADMOD_CCB_VECT)(void);
extern void (* volatile isr_func_CODEC_TIMER_LOADMOD_CCB_VECT)(void);
void isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void);
void isr_SniffISO14443_2A_CODEC_TIMER_LOADMOD_CCB_VECT(void);
@@ -285,4 +287,7 @@ bool CodecIsReaderToBeRestarted(void);
void CodecThresholdSet(uint16_t th);
uint16_t CodecThresholdIncrement(void);
void CodecThresholdReset(void);
#endif /* __ASSEMBLER__ */
#endif /* CODEC_H_ */
+1 -6
View File
@@ -79,13 +79,8 @@ static void StartDemod(void) {
CODEC_DEMOD_IN_PORT.INT0MASK = CODEC_DEMOD_IN_MASK0;
}
ISR(CODEC_DEMOD_IN_INT0_VECT) {
isr_func_CODEC_DEMOD_IN_INT0_VECT();
}
// ISR(CODEC_DEMOD_IN_INT0_VECT)
// Find first pause and start sampling
void isr_ISO14443_2A_TCD0_CCC_vect(void) {
ISR_SHARED isr_ISO14443_2A_TCD0_CCC_vect(void) {
/* This is the first edge of the first modulation-pause after StartDemod.
* Now we have time to start
* demodulating beginning from one bit-width after this edge. */
+174 -128
View File
@@ -4,6 +4,25 @@
* Created on: 25.01.2017
* Author: Phillip Nash
* Modified by: ceres-c
*
* Interrupts information
* - Compare/Capture Channels are used as compare. They're used to sample the field in different moments of time
* - Reader field demodulation events are routed on Event Channel 0, card data modulation on Event Channel 6
* - Reader field demodulation uses Compare Channel C, card data modulation Compare Channel D (PORTB in both cases, of course)
*
* Loadmod code flow:
* Loadmodulation is performed via a state machine inside a ISR, triggered by a counter's (TCD0) overflow interrupt. The interrupt
* is configured in StartISO15693Demod to have a PER (period) equal to ISO15693 t1 nominal time: 4352 carrier pulses.
* (see ISO15693-3:2009, section 9.1).
* Once a EOF is reached when demodulating data from the reader, TCD0's PERBUF register is configured with the period of
* bit transmission (32 carrier pulses). This means that, once the first period overflow is reached (t1 expiration)
* the ISR will output data at the frequency dictated by the standard. This is due to the behaviour of buffered registers, see
* 8045A-AVR-02/08 section 3.7.
*
* Once t1 is reached (the counter overflowed), transmission of data should theoretically begin, but this is not guaranteed,
* due to possible slowdowns of data generation in the currently running Application. Until the application is done,
* the state machine will be stuck in LOADMOD_WAIT state, not outputting any data.
* The ISR will now be invoked every 32 carrier pulses (see ISO15693-2:2006, section 8.2), even when waiting for data.
*/
#include "ISO15693.h"
@@ -12,18 +31,20 @@
#include "LEDHook.h"
#include "AntennaLevel.h"
#include "Terminal/Terminal.h"
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#define SOC_1_OF_4_CODE 0x7B
#define SOC_1_OF_256_CODE 0x7E
#define EOC_CODE 0xDF
#define REQ_SUBCARRIER_SINGLE 0x00
#define REQ_SUBCARRIER_DUAL 0x01
#define REQ_DATARATE_LOW 0x00
#define REQ_DATARATE_HIGH 0x02
#define ISO15693_SAMPLE_CLK TC_CLKSEL_DIV2_gc // 13.56MHz
#define ISO15693_SAMPLE_PERIOD 128 // 9.4us
#define ISO15693_T1_TIME 4352 - 14 /* ISO t1 time - ISR prologue compensation */ // 4192 + 128 + 128 - 1
#define WRITE_GRID_CYCLES 4096
#define SUBCARRIER_1 32
#define SUBCARRIER_2 28
#define SUBCARRIER_OFF 0
@@ -43,7 +64,6 @@
static volatile struct {
volatile bool DemodFinished;
volatile bool LoadmodFinished;
volatile bool DemodAborted;
} Flags = { 0 };
typedef enum {
@@ -78,28 +98,22 @@ static volatile uint8_t ByteCount;
static volatile uint16_t BitRate1;
static volatile uint16_t BitRate2;
static volatile uint16_t SampleDataCount;
static volatile uint16_t ReadCommandFromReader = 0;
#ifdef CONFIG_VICINITY_SUPPORT
/* This function implements CODEC_DEMOD_IN_INT0_VECT interrupt vector.
* It is called when a pulse is detected in CODEC_DEMOD_IN_PORT (PORTB).
* The relevatn interrupt vector is registered to CODEC_DEMOD_IN_MASK0 (PIN1) via:
* The relevant interrupt vector was registered to CODEC_DEMOD_IN_MASK0 (PIN1) via:
* CODEC_DEMOD_IN_PORT.INT0MASK = CODEC_DEMOD_IN_MASK0;
* and unregistered writing the INT0MASK to 0
*/
// ISR(CODEC_DEMOD_IN_INT0_VECT)
void isr_ISO15693_CODEC_DEMOD_IN_INT0_VECT(void) {
/* Start sample timer CODEC_TIMER_SAMPLING (TCD0).
* Set Counter Channel C (CCC) with relevant bitmask (TC0_CCCIF_bm),
* the period for clock sampling is specified in StartISO15693Demod.
*/
ISR_SHARED isr_ISO15693_CODEC_DEMOD_IN_INT0_VECT(void) {
/* Clear Compare Channel C (CCC) interrupt Flags - From 14.12.10 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm;
/* Sets register INTCTRLB to TC_CCCINTLVL_HI_gc = (0x03<<4) to enable compare/capture for high level interrupts on Channel C (CCC) */
/* Enable compare/capture for high level interrupts on Capture Channel C for TCD0 - From 14.12.7 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_HI_gc;
/* Disable this interrupt as we've already sensed the relevant pulse and will use our internal clock from now on */
/* Disable this interrupt. From now on we will sample the field using our internal clock - From 13.13.11 [8331FAVR04/2013] */
CODEC_DEMOD_IN_PORT.INT0MASK = 0;
}
/* This function is called from isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT
@@ -107,36 +121,50 @@ void isr_ISO15693_CODEC_DEMOD_IN_INT0_VECT(void) {
*/
INLINE void ISO15693_EOC(void) {
/* Set bitrate required by the reader on SOF for our following response */
BitRate1 = 256 * 4; // 256 * 4 - 1
if (CodecBuffer[0] & ISO15693_REQ_DATARATE_HIGH)
if (CodecBuffer[0] & REQ_DATARATE_HIGH) {
BitRate1 = 256;
if (CodecBuffer[0] & ISO15693_REQ_SUBCARRIER_DUAL) {
BitRate2 = 252 * 4; // 252 * 4 - 3
if (CodecBuffer[0] & ISO15693_REQ_DATARATE_HIGH)
BitRate2 = 252;
BitRate2 = 252; /* If single subcarrier mode is requested, BitRate2 is useless, but setting it nevertheless was still faster than checking */
} else {
BitRate2 = BitRate1;
BitRate1 = 256 * 4; // Possible value: 256 * 4 - 1
BitRate2 = 252 * 4; // Possible value: 252 * 4 - 3
}
/* Disable event action for CODEC_TIMER_LOADMOD (TCE0) as we're done receiving data */
CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_OFF_gc;
/* Set Counter Channel B (CCB) with relevant bitmask (TC0_CCBIF_bm), the period for clock sampling is specified below */
CODEC_TIMER_LOADMOD.INTFLAGS = TC0_CCBIF_bm; // TODO This might not be needed since commenting it does not break anything
/* Sets register INTCTRLB to TC_CCBINTLVL_HI_gc = (0x03<<2) to enable compare/capture for high level interrupts on channel B */
CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_HI_gc;
/* Set the period for CODEC_TIMER_LOADMOD (TCE0) to Bitrate - 1 because PERBUF is 0-based
*
* TODO Why are we using PERBUF instead of PER?
* With PERBUF the period register will occur on the next overflow.
*/
CODEC_TIMER_LOADMOD.PERBUF = BitRate1 - 1;
Flags.DemodFinished = 1;
/* Sets timer off for CODEC_TIMER_SAMPLING (TCD0) disabling clock source */
/* Disable demodulation interrupt */
/* Sets timer off for TCD0, disabling clock source. We're done receiving data from reader and don't need to probe the antenna anymore - From 14.12.1 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc;
/* Sets register INTCTRLB to 0 to disable all compare/capture interrupts */
CODEC_TIMER_SAMPLING.INTCTRLB = 0;
/* Disable event action for CODEC_TIMER_SAMPLING (TCD0) - From 14.12.4 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc;
/* Disable compare/capture interrupts on Channel C - From 14.12.7 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc;
/* Clear Compare Channel C (CCC) interrupt Flags - From 14.12.10 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm;
/* Enable loadmodulation interrupt */
/* Disable the event action for TCE0 - From 14.12.4 [8331FAVR04/2013] */
CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_OFF_gc;
/* Enable compare/capture for high level interrupts on channel B for TCE0 - From 14.12.7 [8331FAVR04/2013] */
CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_HI_gc;
/* Clear TCE0 interrupt flags for Capture Channel B - From 14.12.10 [8331FAVR04/2013] */
CODEC_TIMER_LOADMOD.INTFLAGS = TC0_CCBIF_bm;
/* Set the BUFFERED PERIOD to Bitrate - 1 (because PERBUF is 0-based).
* The current PERIOD was set in StartISO15693Demod to ISO15693_T1_TIME, once ISO15693_T1_TIME is reached, this will be the new PERIOD.
* From 3.7 [8045A-AVR-02/08] */
CODEC_TIMER_LOADMOD.PERBUF = BitRate1 - 1;
}
/* Disable data demodulation interrupt and inform the codec to restart demodulation from scratch */
INLINE void ISO15693_GARBAGE(void) {
Flags.DemodFinished = 1;
/* Sets timer off for TCD0, disabling clock source. We have demodulated rubbish and don't need to probe the antenna anymore - From 14.12.1 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc;
/* Disable event action for CODEC_TIMER_SAMPLING (TCD0) - From 14.12.4 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc;
/* Disable compare/capture interrupts on Channel C - From 14.12.7 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc;
/* Clear Compare Channel C (CCC) interrupt Flags - From 14.12.10 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm;
}
/* This function is registered to CODEC_TIMER_SAMPLING (TCD0)'s Counter Channel C (CCC).
@@ -144,10 +172,9 @@ INLINE void ISO15693_EOC(void) {
*
* It demodulates bits received from the reader and saves them in CodecBuffer.
*
* It disables its own interrupt when receives an EOF (calling ISO15693_EOC) or when it receives garbage
* It disables its own interrupt when an EOF is found (calling ISO15693_EOC) or when it receives garbage
*/
// ISR(CODEC_TIMER_SAMPLING_CCC_VECT) // Reading data sent from the reader
void isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT(void) {
ISR_SHARED isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT(void) {
/* Shift demod data */
SampleRegister = (SampleRegister << 1) | (!(CODEC_DEMOD_IN_PORT.IN & CODEC_DEMOD_IN_MASK) ? 0x01 : 0x00);
@@ -163,11 +190,7 @@ void isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT(void) {
DemodState = DEMOD_1_OUT_OF_256_STATE;
SampleDataCount = 0;
} else { // No SOC. Restart and try again, we probably received garbage.
Flags.DemodFinished = 1;
/* Sets timer off for CODEC_TIMER_SAMPLING (TCD0) disabling clock source */
CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc;
/* Sets register INTCTRLB to 0 to disable all compare/capture interrupts */
CODEC_TIMER_SAMPLING.INTCTRLB = 0;
ISO15693_GARBAGE();
}
break;
@@ -250,7 +273,6 @@ void isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT(void) {
SampleDataCount++;
}
/* This function is registered to CODEC_TIMER_LOADMOD (TCE0)'s Counter Channel B (CCB).
* When the timer is enabled, this is called on counter's overflow
*
@@ -258,9 +280,9 @@ void isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT(void) {
*
* It disables its own interrupt when all data has been sent
*/
//ISR(CODEC_TIMER_LOADMOD_CCB_VECT)
void isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void) {
ISR_SHARED isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void) {
static void *JumpTable[] = {
[LOADMOD_WAIT] = && LOADMOD_WAIT_LABEL,
[LOADMOD_START_SINGLE] = && LOADMOD_START_SINGLE_LABEL,
[LOADMOD_SOF_SINGLE] = && LOADMOD_SOF_SINGLE_LABEL,
[LOADMOD_BIT0_SINGLE] = && LOADMOD_BIT0_SINGLE_LABEL,
@@ -274,11 +296,11 @@ void isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT(void) {
[LOADMOD_FINISHED] = && LOADMOD_FINISHED_LABEL
};
if ((StateRegister >= LOADMOD_START_SINGLE) && (StateRegister <= LOADMOD_FINISHED)) {
goto *JumpTable[StateRegister];
} else {
return;
}
goto *JumpTable[StateRegister]; /* It takes 28 clock cycles to get here from function entry point */
LOADMOD_WAIT_LABEL:
/* ISO t1 is over, but application is not done generating data yet */
return;
LOADMOD_START_SINGLE_LABEL:
/* Application produced data. With this interrupt we are aligned to the bit-grid. */
@@ -356,9 +378,7 @@ LOADMOD_EOF_SINGLE_LABEL: //End of Manchester encoding
if ((BitSent % 8) == 0) {
/* Last bit has been put out */
StateRegister = LOADMOD_FINISHED;
} else {
StateRegister = LOADMOD_EOF_SINGLE;
}
} /* else: stay in this state. No changes needed */
return;
// -------------------------------------------------------------
@@ -446,24 +466,20 @@ LOADMOD_EOF_DUAL_LABEL: //End of Manchester encoding
if ((BitSent % 8) == 0) {
/* Last bit has been put out */
StateRegister = LOADMOD_FINISHED;
} else {
StateRegister = LOADMOD_EOF_DUAL;
}
} /* else: stay in this state. No changes needed */
return;
LOADMOD_FINISHED_LABEL:
/* Sets timer off for CODEC_TIMER_LOADMOD (TCE0) disabling clock source as we're done modulating */
CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc;
/* Sets register INTCTRLB to 0 to disable all compare/capture interrupts */
CODEC_TIMER_LOADMOD.INTCTRLB = 0;
/* Disable compare/capture for all level interrupts on channel B for TCE0 - From 14.12.7 [8331FAVR04/2013] */
CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_OFF_gc;
CodecSetSubcarrier(CODEC_SUBCARRIERMOD_OFF, 0);
Flags.LoadmodFinished = 1;
return;
}
#endif /* CONFIG_VICINITY_SUPPORT */
/* This functions resets all global variables used in the codec and enables interrupts to wait for reader data */
/* Reset global variables/interrupts to demodulate incoming reader data via ISRs */
void StartISO15693Demod(void) {
/* Reset global variables to default values */
CodecBufferPtr = CodecBuffer;
@@ -479,69 +495,85 @@ void StartISO15693Demod(void) {
ByteCount = 0;
ShiftRegister = 0;
/* Activate Power for demodulator */
CodecSetDemodPower(true);
/* Configure sampling-timer free running and sync to first modulation-pause. */
/* Resets the counter to 0 */
CODEC_TIMER_SAMPLING.CNT = 0;
/* Set the period for CODEC_TIMER_SAMPLING (TCD0) to ISO15693_SAMPLE_PERIOD - 1 because PER is 0-based */
CODEC_TIMER_SAMPLING.PER = ISO15693_SAMPLE_PERIOD - 1;
/* Set Counter Channel C (CCC) register with half bit period - 1. (- 14 to compensate ISR timing overhead) */
CODEC_TIMER_SAMPLING.CCC = ISO15693_SAMPLE_PERIOD / 2 - 14 - 1;
/* Set timer for CODEC_TIMER_SAMPLING (TCD0) to ISO15693_SAMPLE_CLK = TC_CLKSEL_DIV2_gc = System Clock / 2
*
* TODO Why system clock / 2 and not iso period?
/* Set clock source for TCD0 to ISO15693_SAMPLE_CLK = TC_CLKSEL_DIV2_gc = System Clock / 2.
* Since the Chameleon is clocked at 13.56*2 MHz (see Makefile), this counter will hit at the same frequency of reader field.
* From 14.12.1 [8331FAVR04/2013]
*/
CODEC_TIMER_SAMPLING.CTRLA = ISO15693_SAMPLE_CLK;
/* Set event action for CODEC_TIMER_SAMPLING (TCD0) to restart and trigger CODEC_TIMER_MODSTART_EVSEL = TC_EVSEL_CH0_gc = Event Channel 0 */
/* Set up TCD0 action/source:
* - Event Action: Restart waveform period (reset PER register)
* - Event Source Select: trigger on CODEC_TIMER_MODSTART_EVSEL = TC_EVSEL_CH0_gc = Event Channel 0
* From 14.12.4 [8331FAVR04/2013]
*/
CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODSTART_EVSEL;
/* Set Counter Channel C (CCC) with relevant bitmask (TC0_CCCIF_bm), the period for clock sampling is specified above */
CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm;
/* Sets register INTCTRLB to TC_CCCINTLVL_OFF_gc = (0x00<<4) to disable compare/capture C interrupts
*
* TODO Why turn it off?
*/
CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc;
/* Resets the sampling counter (TCD0) to 0 - From 14.12.12 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.CNT = 0;
/* Set event action for CODEC_TIMER_LOADMOD (TCE0) to restart and trigger CODEC_TIMER_MODSTART_EVSEL = TC_EVSEL_CH0_gc = Event Channel 0 */
CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODSTART_EVSEL;
/* Set the period for CODEC_TIMER_LOADMOD (TCE0) to... some magic numbers?
* Using PER instead of PERBUF breaks it when receiving ISO15693_APP_NO_RESPONSE from Application.
*
* TODO What are these numbers?
/* Set Clock Source for TCE0 to CODEC_TIMER_CARRIER_CLKSEL = TC_CLKSEL_EVCH6_gc = Event Channel 6 */
CODEC_TIMER_LOADMOD.CTRLA = CODEC_TIMER_CARRIER_CLKSEL;
/* Set up TCE0 action/source:
* - Event Action: Restart waveform period (reset PER register)
* - Event Source Select: trigger on CODEC_TIMER_MODSTART_EVSEL = TC_EVSEL_CH0_gc = Event Channel 0
* From 14.12.4 [8331FAVR04/2013]
*/
CODEC_TIMER_LOADMOD.PERBUF = 4192 + 128 + 128 - 1;
/* Sets register INTCTRLA to 0 to disable timer error or overflow interrupts */
CODEC_TIMER_LOADMOD.INTCTRLA = 0;
/* Sets register INTCTRLB to 0 to disable all compare/capture interrupts */
CODEC_TIMER_LOADMOD.INTCTRLB = 0;
/* Set timer for CODEC_TIMER_SAMPLING (TCD0) to TC_CLKSEL_EVCH6_gc = Event Channel 6 */
CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_EVCH6_gc;
CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODSTART_EVSEL;
/* Temporarily disable compare/capture for all level interrupts on channel B for TCE0. They'll be enabled later when load modulation will be needed.
* From 14.12.7 [8331FAVR04/2013] */
CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_OFF_gc;
/* Set the period for CODEC_TIMER_LOADMOD (TCE0) ISO standard t1 time.
* Once this timer is enabled, it will wait for a time equal to t1 and then its ISR will be called.
* From 14.12.18 [8331FAVR04/2013]
*/
CODEC_TIMER_LOADMOD.PER = ISO15693_T1_TIME;
/* Start looking out for modulation pause via interrupt. */
/* Sets register INTFLAGS to PORT_INT0LVL_HI_gc = (0x03<<0) to enable compare/capture for high level interrupts on CODEC_DEMOD_IN_PORT (PORTB) */
CODEC_DEMOD_IN_PORT.INTFLAGS = PORT_INT0LVL_HI_gc;
/* Sets INT0MASK to CODEC_DEMOD_IN_MASK0 = PIN1_bm to use it as source for port interrupt 0 */
/* Clear PORTB interrupt flags - From 13.13.13 [8331FAVR04/2013] */
CODEC_DEMOD_IN_PORT.INTFLAGS = PORT_INT0IF_bm;
/* Use PIN1 as a source for modulation pauses. Will trigger PORTB Interrput 0 - From 13.13.11 [8331FAVR04/2013] */
CODEC_DEMOD_IN_PORT.INT0MASK = CODEC_DEMOD_IN_MASK0;
}
/* Configure unvarying interrupts settings.
* All configured interrupts will still be disabled once this function is done, they'll be enabled one by one as the communication flow requires them.
*/
void ISO15693CodecInit(void) {
CodecInitCommon();
/* Register isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT function
* to CODEC_TIMER_SAMPLING (TCD0)'s Counter Channel C (CCC)
*/
/**************************************************
* Register function handlers to shared ISR *
**************************************************/
/* Register isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT function to CODEC_TIMER_SAMPLING (TCD0)'s Counter Channel C (CCC) */
isr_func_TCD0_CCC_vect = &isr_ISO15693_CODEC_TIMER_SAMPLING_CCC_VECT;
/* Register isr_ISO15693_CODEC_DEMOD_IN_INT0_VECT function
* to CODEC_DEMOD_IN_PORT (PORTB) interrupt 0
*/
/* Register isr_ISO15693_CODEC_DEMOD_IN_INT0_VECT function to CODEC_DEMOD_IN_PORT (PORTB) interrupt 0 */
isr_func_CODEC_DEMOD_IN_INT0_VECT = &isr_ISO15693_CODEC_DEMOD_IN_INT0_VECT;
/* Register isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT function
* to CODEC_TIMER_LOADMOD (TCE0)'s Counter Channel B (CCB)
*/
/* Register isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT function to CODEC_TIMER_LOADMOD (TCE0)'s Counter Channel B (CCB) */
isr_func_CODEC_TIMER_LOADMOD_CCB_VECT = &isr_ISO15693_CODEC_TIMER_LOADMOD_CCB_VECT;
/**************************************************
* Configure demod interrupt *
**************************************************/
/* Configure sampling-timer free running and sync to first modulation-pause */
/* Set the period for TCD0 to ISO15693_SAMPLE_PERIOD - 1 because PER is 0-based - From 14.12.14 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.PER = ISO15693_SAMPLE_PERIOD - 1;
/* Set Compare Channel C (CCC) period to half bit period - 1. (- 14 to compensate ISR timing overhead) - From 14.12.16 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.CCC = ISO15693_SAMPLE_PERIOD / 2 - 14 - 1;
/* Temporarily disable Compare Channel C (CCC) interrupts.
* They'll be enabled later in isr_ISO15693_CODEC_DEMOD_IN_INT0_VECT once we sensed the reader is sending data and we're in sync with the pulses.
* From 14.12.7 [8331FAVR04/2013]
*/
CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc;
/* Clear Compare Channel C (CCC) interrupt Flags - From 14.12.10 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm;
/**************************************************
* Configure loadmod interrupt *
**************************************************/
/* Disable timer error and overflow interrupts - From 14.12.6 [8331FAVR04/2013] */
CODEC_TIMER_LOADMOD.INTCTRLA = 0;
/* Activate Power for demodulator */
CodecSetDemodPower(true);
StartISO15693Demod();
}
@@ -564,21 +596,21 @@ void ISO15693CodecDeInit(void) {
ShiftRegister = 0;
/* Disable sample timer */
/* Sets timer off for CODEC_TIMER_SAMPLING (TCD0) disabling clock source */
/* Sets timer off for TCD0, disabling clock source - From 14.12.1 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc;
/* Disable event action for CODEC_TIMER_SAMPLING (TCD0) */
/* Disable event action for CODEC_TIMER_SAMPLING (TCD0) - From 14.12.4 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc;
/* Sets register INTCTRLB to TC_CCCINTLVL_OFF_gc = (0x00<<4) to disable compare/capture C interrupts */
/* Disable Compare Channel C (CCC) interrupts - From 14.12.7 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc;
/* Restore Counter Channel C (CCC) interrupt mask (TC0_CCCIF_bm) */
/* Clear Compare Channel C (CCC) interrupt Flags - From 14.12.10 [8331FAVR04/2013] */
CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm;
/* Disable load modulation */
/* Disable event action for CODEC_TIMER_LOADMOD (TCE0) */
/* Disable the event action for TCE0 - From 14.12.4 [8331FAVR04/2013] */
CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_OFF_gc;
/* Sets register INTCTRLB to TC_CCBINTLVL_OFF_gc = (0x00<<2) to disable compare/capture B interrupts */
/* Disable compare/capture for all level interrupts on channel B for TCE0 - From 14.12.7 [8331FAVR04/2013] */
CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_OFF_gc;
/* Restore Counter Channel B (CCB) interrupt mask (TC0_CCBIF_bm) */
/* Clear TCE0 interrupt flags for Capture Channel B - From 14.12.10 [8331FAVR04/2013] */
CODEC_TIMER_LOADMOD.INTFLAGS = TC0_CCBIF_bm;
CodecSetSubcarrier(CODEC_SUBCARRIERMOD_OFF, 0);
@@ -598,7 +630,7 @@ void ISO15693CodecTask(void) {
LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, DemodByteCount);
LEDHook(LED_CODEC_RX, LED_PULSE);
if (CodecBuffer[0] & ISO15693_REQ_SUBCARRIER_DUAL) {
if (CodecBuffer[0] & REQ_SUBCARRIER_DUAL) {
bDualSubcarrier = true;
}
AppReceivedByteCount = ApplicationProcess(CodecBuffer, DemodByteCount);
@@ -606,7 +638,13 @@ void ISO15693CodecTask(void) {
/* This is only reached when we've received a valid frame */
if (AppReceivedByteCount != ISO15693_APP_NO_RESPONSE) {
LogEntry(LOG_INFO_CODEC_TX_DATA, CodecBuffer, AppReceivedByteCount);
if (AppReceivedByteCount > CODEC_BUFFER_SIZE - ISO15693_CRC16_SIZE) { /* CRC would be written outside codec buffer */
CodecBuffer[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR;
CodecBuffer[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_NOT_SUPP;
AppReceivedByteCount = 2;
LogEntry(LOG_INFO_GENERIC, "Too much data requested - See PR #274", 38);
}
LEDHook(LED_CODEC_TX, LED_PULSE);
ByteCount = AppReceivedByteCount;
@@ -621,13 +659,21 @@ void ISO15693CodecTask(void) {
StateRegister = LOADMOD_START_SINGLE;
}
} else {
/* No data to process. Disable CODEC_TIMER_LOADMOD (TCE0) counter and start listening again */
/* Sets timer off for CODEC_TIMER_LOADMOD (TCE0) disabling clock source as we're done modulating */
CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc;
/* Sets register INTCTRLB to 0 to disable all compare/capture interrupts */
CODEC_TIMER_LOADMOD.INTCTRLB = 0;
/* Calculate the CRC while modulation is already ongoing */
ISO15693AppendCRC(CodecBuffer, AppReceivedByteCount);
ByteCount += ISO15693_CRC16_SIZE; /* Increase this variable as it will be read by the codec during loadmodulation */
LogEntry(LOG_INFO_CODEC_TX_DATA, CodecBuffer, AppReceivedByteCount + ISO15693_CRC16_SIZE);
} else {
/* Overwrite the PERBUF register, which was configured in ISO15693_EOC, with the new appropriate value.
* This is expecially needed because, since load modulation has not been performed, we're jumping here straight after
* ISO15693_EOC. This implies that the data stored in the PERBUF register by ISO15693_EOC still has to be copied
* in the PER register and that will happen on the next UPDATE event.
* The next UPDATE event will be timer/counter enablement in ISO15693_EOC, which is executed after StartISO15693Demod,
* effectively overwriting PER with an incorrect value.
* See 8045A-AVR-02/08 section 3.7 for information about buffered registers.
*/
CODEC_TIMER_LOADMOD.PERBUF = ISO15693_T1_TIME;
StartISO15693Demod();
}
}
-20
View File
@@ -8,26 +8,8 @@
#ifndef ISO15693_H_
#define ISO15693_H_
#include "Terminal/CommandLine.h"
#define ISO15693_APP_NO_RESPONSE 0x0000
#define SUBCARRIER_1 32
#define SUBCARRIER_2 28
#define SUBCARRIER_OFF 0
#define SOF_PATTERN 0x1D
#define EOF_PATTERN 0xB8
#define T1_NOMINAL_CYCLES 4352 - 14//4352 - 25 /* ISR prologue compensation */
#define WRITE_GRID_CYCLES 4096
//Used when checking the request sent from the reader
#define ISO15693_REQ_SUBCARRIER_SINGLE 0x00
#define ISO15693_REQ_SUBCARRIER_DUAL 0x01
#define ISO15693_REQ_DATARATE_LOW 0x00
#define ISO15693_REQ_DATARATE_HIGH 0x02
/* Codec Interface */
void ISO15693CodecInit(void);
void ISO15693CodecDeInit(void);
@@ -37,6 +19,4 @@ void ISO15693CodecTask(void);
void ISO15693CodecStart(void);
void ISO15693CodecReset(void);
#endif /* ISO15693_H_ */
@@ -170,13 +170,10 @@ INLINE void BufferToSequence(void) {
if (BitCount % 8)
CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8));
}
// Frame Delay Time PCD to PICC ends
ISR(CODEC_TIMER_SAMPLING_CCC_VECT) {
isr_func_TCD0_CCC_vect();
}
// ISR (TCD0_CCC_vect)
void isr_Reader14443_2A_TCD0_CCC_vect(void) {
// Frame Delay Time PCD to PICC ends
ISR_SHARED isr_Reader14443_2A_TCD0_CCC_vect(void) {
CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm;
CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc;
@@ -56,6 +56,8 @@ static volatile uint16_t ReaderBitCount;
static volatile uint16_t CardBitCount;
static volatile uint16_t rawBitCount;
enum RCTraffic TrafficSource;
INLINE void CardSniffInit(void);
INLINE void CardSniffDeinit(void);
@@ -351,16 +353,13 @@ ISR(ACA_AC0_vect) { // this interrupt either finds the SOC or gets triggered bef
StateRegister = PICC_FRAME;
}
ISR(CODEC_TIMER_LOADMOD_CCB_VECT) { // pause found
isr_func_CODEC_TIMER_LOADMOD_CCB_VECT();
}
// Called once a pause is found
// Decode the Card -> Reader signal
// according to the pause and modulated period
// if the half bit duration is modulated, then add 1 to buffer
// if the half bit duration is not modulated, then add 0 to buffer
//ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found
void isr_SniffISO14443_2A_CODEC_TIMER_LOADMOD_CCB_VECT(void) {
ISR_SHARED isr_SniffISO14443_2A_CODEC_TIMER_LOADMOD_CCB_VECT(void) {
uint8_t tmp = CODEC_TIMER_TIMESTAMPS.CNTL;
CODEC_TIMER_TIMESTAMPS.CNT = 0;
@@ -9,7 +9,7 @@
#include "Codec.h"
#include "Terminal/CommandLine.h"
enum RCTraffic {TRAFFIC_READER, TRAFFIC_CARD} TrafficSource;
extern enum RCTraffic {TRAFFIC_READER, TRAFFIC_CARD} TrafficSource;
/* Codec Interface */
void Sniff14443ACodecInit(void);
void Sniff14443ACodecDeInit(void);
+3
View File
@@ -17,6 +17,9 @@
#define ODD_PARITY(Value) OddParityBit(Value)//(parity_even_bit(Value) ? 0 : 1)
#define ISR_SHARED \
void __attribute__((signal)) // This function type has to be used for all the interrupt handlers that have to be changed at runtime
#define INLINE \
static inline __attribute__((always_inline))
+49
View File
@@ -0,0 +1,49 @@
; This file allows to share ISR at runtime with a low overhead.
; Functions that have to be shared MUST be defined as ISR_SHARED types
; (Defined in Common.h) to instruct GCC to compile them preserving the stack
;
; Created on: 2019-12-06
; Author: ceres-c
;
#include "Codec/Codec.h"
#include <avr/interrupt.h>
; Macro to call ISR functions
; For development purposes: cycles penality before landing in the Shared ISR is 10
.macro call_isr isr_address
push r30 ; 1
push r31 ; 1
lds r30, \isr_address ; 3
lds r31, \isr_address+1 ; 3
icall ; 2 (16 bit PC)
pop r31
pop r30
reti
.endm
; Shared ISR must be defined below as globals
; Example:
;
; .global <INTERRUPT-TO-SHARE>
; INTERRUPT-TO-SHARE:
; call_isr POINTER-TO-VARIABLE-INTERRUPT-HANDLER
;
; Where:
; INTERRUPT-TO-SHARE
; The target interrupt which needs to be shared
; POINTER-TO-VARIABLE-INTERRUPT-HANDLER
; A pointer to the interrupt handler which can be modified at runtime.
; Must be a volatile pointer to function declared in Codec.h
.global CODEC_DEMOD_IN_INT0_VECT
CODEC_DEMOD_IN_INT0_VECT:
call_isr isr_func_CODEC_DEMOD_IN_INT0_VECT
.global CODEC_TIMER_SAMPLING_CCC_VECT
CODEC_TIMER_SAMPLING_CCC_VECT:
call_isr isr_func_TCD0_CCC_vect
.global CODEC_TIMER_LOADMOD_CCB_VECT
CODEC_TIMER_LOADMOD_CCB_VECT:
call_isr isr_func_CODEC_TIMER_LOADMOD_CCB_VECT
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -97,7 +97,7 @@ F_CPU = 27120000
F_USB = 48000000
TARGET = Chameleon-Mini
OPTIMIZATION = s
SRC += $(TARGET).c LUFADescriptors.c System.c Configuration.c Random.c Common.c Memory.c MemoryAsm.S Button.c Log.c Settings.c LED.c Map.c AntennaLevel.c
SRC += $(TARGET).c LUFADescriptors.c System.c ISRSharing.S Configuration.c Random.c Common.c Memory.c MemoryAsm.S Button.c Log.c Settings.c LED.c Map.c AntennaLevel.c
SRC += Terminal/Terminal.c Terminal/Commands.c Terminal/XModem.c Terminal/CommandLine.c
SRC += Codec/Codec.c Codec/ISO14443-2A.c Codec/Reader14443-2A.c Codec/SniffISO14443-2A.c Codec/Reader14443-ISR.S
SRC += Application/MifareUltralight.c Application/MifareClassic.c Application/ISO14443-3A.c Application/Crypto1.c Application/Reader14443A.c Application/Sniff14443A.c Application/CryptoTDEA.S

Some files were not shown because too many files have changed in this diff Show More