Chameleon-Mini
Codec.h
1 /*
2  * CODEC.h
3  *
4  * Created on: 18.02.2013
5  * Author: skuser
6  */
7 
8 #ifndef CODEC_H_
9 #define CODEC_H_
10 
11 #include <avr/io.h>
12 #include <stdint.h>
13 #include <stdbool.h>
14 #include "../Common.h"
15 #include "../Configuration.h"
16 
17 #include "ISO14443-2A.h"
18 #include "Reader14443-2A.h"
19 
20 /* Timing definitions for ISO14443A */
21 #define ISO14443A_SUBCARRIER_DIVIDER 16
22 #define ISO14443A_BIT_GRID_CYCLES 128
23 #define ISO14443A_BIT_RATE_CYCLES 128
24 #define ISO14443A_FRAME_DELAY_PREV1 1236
25 #define ISO14443A_FRAME_DELAY_PREV0 1172
26 #define ISO14443A_RX_PENDING_TIMEOUT 1 // ms
27 
28 /* Peripheral definitions */
29 #define CODEC_DEMOD_POWER_PORT PORTB
30 #define CODEC_DEMOD_POWER_MASK PIN0_bm
31 #define CODEC_DEMOD_IN_PORT PORTB
32 #define CODEC_DEMOD_IN_MASK (CODEC_DEMOD_IN_MASK0 | CODEC_DEMOD_IN_MASK1)
33 #define CODEC_DEMOD_IN_MASK0 PIN1_bm
34 #define CODEC_DEMOD_IN_MASK1 PIN2_bm
35 #define CODEC_DEMOD_IN_PINCTRL0 PIN1CTRL
36 #define CODEC_DEMOD_IN_PINCTRL1 PIN2CTRL
37 #define CODEC_DEMOD_IN_EVMUX0 EVSYS_CHMUX_PORTB_PIN1_gc
38 #define CODEC_DEMOD_IN_EVMUX1 EVSYS_CHMUX_PORTB_PIN2_gc
39 #define CODEC_DEMOD_IN_INT0_VECT PORTB_INT0_vect
40 #define CODEC_LOADMOD_PORT PORTC
41 #define CODEC_LOADMOD_MASK PIN6_bm
42 #define CODEC_CARRIER_IN_PORT PORTC
43 #define CODEC_CARRIER_IN_MASK PIN2_bm
44 #define CODEC_CARRIER_IN_PINCTRL PIN2CTRL
45 #define CODEC_CARRIER_IN_EVMUX EVSYS_CHMUX_PORTC_PIN2_gc
46 #define CODEC_CARRIER_IN_DIV 2 /* external clock division factor */
47 #define CODEC_SUBCARRIER_PORT PORTC
48 #define CODEC_SUBCARRIER_MASK_PSK PIN4_bm
49 #define CODEC_SUBCARRIER_MASK_OOK PIN5_bm
50 #define CODEC_SUBCARRIER_MASK (CODEC_SUBCARRIER_MASK_PSK | CODEC_SUBCARRIER_MASK_OOK)
51 #define CODEC_SUBCARRIER_TIMER TCC1
52 #define CODEC_SUBCARRIER_CC_PSK CCA
53 #define CODEC_SUBCARRIER_CC_OOK CCB
54 #define CODEC_SUBCARRIER_CCEN_PSK TC1_CCAEN_bm
55 #define CODEC_SUBCARRIER_CCEN_OOK TC1_CCBEN_bm
56 #define CODEC_TIMER_SAMPLING TCD0
57 #define CODEC_TIMER_SAMPLING_CCA_VECT TCD0_CCA_vect
58 #define CODEC_TIMER_SAMPLING_CCB_VECT TCD0_CCB_vect
59 #define CODEC_TIMER_LOADMOD TCE0
60 #define CODEC_TIMER_LOADMOD_OVF_VECT TCE0_OVF_vect
61 #define CODEC_TIMER_LOADMOD_CCA_VECT TCE0_CCA_vect
62 #define CODEC_TIMER_LOADMOD_CCB_VECT TCE0_CCB_vect
63 #define CODEC_TIMER_LOADMOD_CCC_VECT TCE0_CCC_vect
64 #define CODEC_TIMER_MODSTART_EVSEL TC_EVSEL_CH0_gc
65 #define CODEC_TIMER_MODEND_EVSEL TC_EVSEL_CH1_gc
66 #define CODEC_TIMER_CARRIER_CLKSEL TC_CLKSEL_EVCH6_gc
67 #define CODEC_READER_TIMER TCC0
68 #define CODEC_READER_PORT PORTC
69 #define CODEC_READER_MASK_LEFT PIN0_bm
70 #define CODEC_READER_MASK_RIGHT PIN1_bm
71 #define CODEC_READER_MASK (CODEC_READER_MASK_LEFT | CODEC_READER_MASK_RIGHT)
72 #define CODEC_READER_PINCTRL_LEFT PIN0CTRL
73 #define CODEC_READER_PINCTRL_RIGHT PIN1CTRL
74 #define CODEC_AC_DEMOD_SETTINGS AC_HSMODE_bm | AC_HYSMODE_NO_gc
75 #define CODEC_MAXIMUM_THRESHOLD 0xFFF // the maximum voltage can be calculated with ch0data * Vref / 0xFFF
76 #define CODEC_TIMER_TIMESTAMPS TCD1
77 #define CODEC_TIMER_TIMESTAMPS_CCA_VECT TCD1_CCA_vect
78 
79 #define CODEC_BUFFER_SIZE 256
80 
81 #define CODEC_CARRIER_FREQ 13560000
82 
83 #define Codec8Reg0 GPIOR0
84 #define Codec8Reg1 GPIOR1
85 #define Codec8Reg2 GPIOR2
86 #define Codec8Reg3 GPIOR3
87 #define CodecCount16Register1 (*((volatile uint16_t*) &GPIOR4)) /* GPIOR4 & GPIOR5 */
88 #define CodecCount16Register2 (*((volatile uint16_t*) &GPIOR6)) /* GPIOR4 & GPIOR5 */
89 #define CodecPtrRegister1 (*((volatile uint8_t**) &GPIOR8))
90 #define CodecPtrRegister2 (*((volatile uint8_t**) &GPIORA))
91 
92 extern uint16_t ReaderThreshold;
93 
94 typedef enum {
95  CODEC_SUBCARRIERMOD_OFF,
96  CODEC_SUBCARRIERMOD_OOK
97 } SubcarrierModType;
98 
99 extern uint8_t CodecBuffer[CODEC_BUFFER_SIZE];
100 
101 INLINE void CodecInit(void) {
102  ActiveConfiguration.CodecInitFunc();
103 }
104 
105 INLINE void CodecDeInit(void) {
106  ActiveConfiguration.CodecDeInitFunc();
107 }
108 
109 INLINE void CodecTask(void) {
110  ActiveConfiguration.CodecTaskFunc();
111 }
112 
113 /* Helper Functions for Codec implementations */
114 INLINE void CodecInitCommon(void)
115 {
116  /* Configure CARRIER input pin and route it to EVSYS.
117  * Multiply by 2 again by using both edges when externally
118  * dividing by 2 */
119 #if CODEC_CARRIER_IN_DIV == 2
120  CODEC_CARRIER_IN_PORT.CODEC_CARRIER_IN_PINCTRL = PORT_ISC_BOTHEDGES_gc;
121 #else
122 #error Option not supported
123 #endif
124  CODEC_CARRIER_IN_PORT.DIRCLR = CODEC_CARRIER_IN_MASK;
125  EVSYS.CH6MUX = CODEC_CARRIER_IN_EVMUX;
126 
127  /* Configure two DEMOD pins for input.
128  * Configure event channel 0 for rising edge (begin of modulation pause)
129  * Configure event channel 1 for falling edge (end of modulation pause) */
130  CODEC_DEMOD_POWER_PORT.OUTCLR = CODEC_DEMOD_POWER_MASK;
131  CODEC_DEMOD_POWER_PORT.DIRSET = CODEC_DEMOD_POWER_MASK;
132  CODEC_DEMOD_IN_PORT.DIRCLR = CODEC_DEMOD_IN_MASK;
133  CODEC_DEMOD_IN_PORT.CODEC_DEMOD_IN_PINCTRL0 = PORT_ISC_RISING_gc;
134  CODEC_DEMOD_IN_PORT.CODEC_DEMOD_IN_PINCTRL1 = PORT_ISC_FALLING_gc;
135  CODEC_DEMOD_IN_PORT.INT0MASK = 0;
136  CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT0LVL_HI_gc;
137  EVSYS.CH0MUX = CODEC_DEMOD_IN_EVMUX0;
138  EVSYS.CH1MUX = CODEC_DEMOD_IN_EVMUX1;
139 
140  /* Configure loadmod pin configuration and use a virtual port configuration
141  * for single instruction cycle access */
142  CODEC_LOADMOD_PORT.DIRSET = CODEC_LOADMOD_MASK;
143  CODEC_LOADMOD_PORT.OUTCLR = CODEC_LOADMOD_MASK;
144  PORTCFG.VPCTRLA &= ~PORTCFG_VP0MAP_gm;
145  PORTCFG.VPCTRLA |= PORTCFG_VP02MAP_PORTC_gc;
146 
147  /* Configure subcarrier pins for output */
148  CODEC_SUBCARRIER_PORT.DIRSET = CODEC_SUBCARRIER_MASK;
149  CODEC_SUBCARRIER_PORT.OUTCLR = CODEC_SUBCARRIER_MASK;
150 
151  /* Configure pins for reader field with the LEFT output being inverted
152  * and all bridge outputs static high */
153  CODEC_READER_PORT.CODEC_READER_PINCTRL_LEFT = PORT_INVEN_bm;
154  CODEC_READER_PORT.OUTCLR = CODEC_READER_MASK_LEFT;
155  CODEC_READER_PORT.OUTSET = CODEC_READER_MASK_RIGHT;
156  CODEC_READER_PORT.DIRSET = CODEC_READER_MASK;
157 
158  /* Configure timer for generating reader field and configure AWEX for outputting pattern
159  * with disabled outputs. */
160  CODEC_READER_TIMER.CTRLB = TC0_CCAEN_bm | TC_WGMODE_SINGLESLOPE_gc;
161  CODEC_READER_TIMER.PER = F_CPU / CODEC_CARRIER_FREQ - 1;
162  CODEC_READER_TIMER.CCA = F_CPU / CODEC_CARRIER_FREQ / 2 ;
163 
164  AWEXC.OUTOVEN = 0x00;
165  AWEXC.CTRL = AWEX_CWCM_bm | AWEX_DTICCAEN_bm | AWEX_DTICCBEN_bm;
166 
167  /* Configure DAC for the reference voltage */
168  DACB.EVCTRL = 0;
169  DACB.CTRLB = DAC_CHSEL_SINGLE_gc;
170  DACB.CTRLC = DAC_REFSEL_AVCC_gc;
171  DACB.CTRLA = DAC_IDOEN_bm | DAC_ENABLE_bm;
172  DACB.CH0DATA = ReaderThreshold; // real threshold voltage can be calculated with ch0data * Vref / 0xFFF
173 
174  /* Configure Analog Comparator 0 to detect changes in demodulated reader field */
175  ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc;
176  ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS;
177 
178  /* Configure Analog Comparator 1 to detect SOC */
179  ACA.AC1MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc;
180  ACA.AC1CTRL = CODEC_AC_DEMOD_SETTINGS;
181 }
182 
183 INLINE void CodecSetSubcarrier(SubcarrierModType ModType, uint16_t Divider)
184 {
185  if (ModType == CODEC_SUBCARRIERMOD_OFF) {
186  CODEC_SUBCARRIER_TIMER.CTRLA = TC_CLKSEL_OFF_gc;
187  CODEC_SUBCARRIER_TIMER.CTRLB = 0;
188  } else if (ModType == CODEC_SUBCARRIERMOD_OOK) {
189  /* Configure subcarrier generation with 50% DC output using OOK */
190  CODEC_SUBCARRIER_TIMER.CNT = 0;
191  CODEC_SUBCARRIER_TIMER.PER = Divider - 1;
192  CODEC_SUBCARRIER_TIMER.CODEC_SUBCARRIER_CC_OOK = Divider/2;
193  CODEC_SUBCARRIER_TIMER.CTRLB = CODEC_SUBCARRIER_CCEN_OOK | TC_WGMODE_SINGLESLOPE_gc;
194  }
195 }
196 
197 INLINE void CodecStartSubcarrier(void)
198 {
199  CODEC_SUBCARRIER_TIMER.CTRLA = CODEC_TIMER_CARRIER_CLKSEL;
200 }
201 
202 INLINE void CodecSetDemodPower(bool bOnOff)
203 {
204  if (bOnOff) {
205  CODEC_DEMOD_POWER_PORT.OUTSET = CODEC_DEMOD_POWER_MASK;
206  } else {
207  CODEC_DEMOD_POWER_PORT.OUTCLR = CODEC_DEMOD_POWER_MASK;
208  }
209 }
210 
211 INLINE bool CodecGetLoadmodState(void) {
212  if (ACA.STATUS & AC_AC0STATE_bm) {
213  return true;
214  } else {
215  return false;
216  }
217 }
218 
219 INLINE void CodecSetLoadmodState(bool bOnOff) {
220  if (bOnOff) {
221  VPORT0.OUT |= CODEC_LOADMOD_MASK;
222  } else {
223  VPORT0.OUT &= ~CODEC_LOADMOD_MASK;
224  }
225 }
226 
227 INLINE void CodecSetReaderField(bool bOnOff) { // this is the function for turning on/off the reader field dumbly; before using this function, please consider to use CodecReaderField{Start,Stop}
228 
229  if (bOnOff) {
230  /* Start timer for field generation and unmask outputs */
231  CODEC_READER_TIMER.CTRLA = TC_CLKSEL_DIV1_gc;
232  AWEXC.OUTOVEN = CODEC_READER_MASK;
233  } else {
234  /* Disable outputs of AWEX and stop field generation */
235  AWEXC.OUTOVEN = 0x00;
236  CODEC_READER_TIMER.CTRLA = TC_CLKSEL_OFF_gc;
237  }
238 }
239 
240 INLINE bool CodecGetReaderField(void) {
241  return (CODEC_READER_TIMER.CTRLA == TC_CLKSEL_DIV1_gc) && (AWEXC.OUTOVEN == CODEC_READER_MASK);
242 }
243 
244 void CodecReaderFieldStart(void);
245 void CodecReaderFieldStop(void);
246 bool CodecIsReaderFieldReady(void);
247 
248 #endif /* CODEC_H_ */
void(* CodecInitFunc)(void)
Definition: Configuration.h:57
void(* CodecTaskFunc)(void)
Definition: Configuration.h:63
void(* CodecDeInitFunc)(void)
Definition: Configuration.h:59