paths changed
[kk_librfid.git] / firmware / src / pcd / .svn / text-base / main_pwm.c.svn-base
blob7db6b72004613862733c0ed524ca6e3d11d75177
1 /* main_pwm - OpenPCD firmware for generating a PWM-modulated 13.56MHz
2  *            carrier
3  *
4  * To use this, you need to connect PIOA P0 with MFIN of the reader.
5  *
6  * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by 
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
24 #include <errno.h>
25 #include <string.h>
26 #include <lib_AT91SAM7.h>
27 #include "../openpcd.h"
28 #include <pcd/rc632.h>
29 #include <os/dbgu.h>
30 #include <os/led.h>
31 #include <os/pwm.h>
32 #include <os/tc_cdiv.h>
33 #include <os/pcd_enumerate.h>
34 #include <os/usb_handler.h>
36 #ifdef SSC
37 #include <pcd/ssc.h>
38 #endif
40 #define RAH NULL
42 static u_int8_t force_100ask = 1;
43 static u_int8_t mod_conductance = 0x3f;
44 static u_int8_t cw_conductance = 0x3f;
45 static u_int16_t duty_percent = 22;
47 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
48 static u_int32_t pwm_freq[] = { 105937, 211875, 423750, 847500 };
49 static u_int8_t pwm_freq_idx = 0;
51 static void rc632_modulate_mfin()
53         opcd_rc632_reg_write(RAH, RC632_REG_TX_CONTROL, 
54                         RC632_TXCTRL_MOD_SRC_MFIN|RC632_TXCTRL_TX2_INV|
55                         RC632_TXCTRL_TX1_RF_EN|RC632_TXCTRL_TX2_RF_EN);
58 /* (77/40) ^ EXPcsCfgCW */
59 /* 1, 1.925, 3.705625, 7.13332812 */
61 #define COND_MANT(x)    (x & 0x0f)
62 #define COND_EXP(x)     ((x & 0x30) >> 4)
64 static const u_int16_t rsrel_expfact[] = { 1000, 1925, 3706, 7133 };
66 static u_int32_t calc_conduct_rel(u_int8_t inp)
68         u_int32_t cond_rel;
70         cond_rel = COND_MANT(inp) * rsrel_expfact[COND_EXP(inp)];
71         cond_rel = cond_rel / 1000;
73         return cond_rel;
76 static const u_int8_t rsrel_table[] = {
77         0, 16, 32, 48, 1, 17, 2, 3, 33, 18, 4, 5, 19, 6, 7, 49, 34, 20,
78         8, 9, 21, 10, 11, 35, 22, 12, 13, 23, 14, 50, 36, 15, 24, 25,
79         37, 26, 27, 51, 38, 28, 29, 39, 30, 52, 31, 40, 41, 53, 42, 43,
80         54, 44, 45, 55, 46, 47, 56, 57, 58, 59, 60, 61, 62, 63 };
83 static const u_int16_t cdivs[] = { 128, 64, 32, 16 };
84 static int cdiv_idx = 0;
86 static void help(void)
88         DEBUGPCR("o: decrease duty     p: increase duty\r\n"
89                  "k: stop pwm          l: start pwn\r\n"
90                  "n: decrease freq     m: incresae freq\r\n"
91                  "v: decrease mod_cond b: increase mod_cond\r\n"
92                  "g: decrease cw_cond  h: increase cw_cond");
93         DEBUGPCR("u: PA23 const 1      y: PA23 const 0\r\n"
94                  "t: PA23 PWM0         f: toggle Force100ASK\r\n"
95                  "{: decrease cdiv_idx }: increse cdiv idx");
98 void _init_func(void)
100         DEBUGPCR("\r\n===> main_pwm <===\r\n");
101         help();
103         rc632_init();
104         DEBUGPCRF("turning on RF");
105         rc632_turn_on_rf(RAH);
107         /* switch PA17 (connected to MFIN on board) to input */
108         AT91F_PIO_CfgInput(AT91C_BASE_PIOA, AT91C_PIO_PA17);
110         DEBUGPCRF("Initializing carrier divider");
111         tc_cdiv_init();
113         DEBUGPCRF("Initializing PWM");
114         pwm_init();
115         pwm_freq_set(0, 105937);
116         pwm_start(0);
117         pwm_duty_set_percent(0, 22);    /* 22% of 9.43uS = 2.07uS */
118         rc632_modulate_mfin();
120 #ifdef SSC
121         DEBUGPCRF("Initializing SSC RX");
122         ssc_rx_init();
123 #endif
126 int _main_dbgu(char key)
128         switch (key) {
129         case 'o':
130                 if (duty_percent >= 1)
131                         duty_percent--;
132                 pwm_duty_set_percent(0, duty_percent);
133                 break;
134         case 'p':
135                 if (duty_percent <= 99)
136                         duty_percent++;
137                 pwm_duty_set_percent(0, duty_percent);
138                 break;
139         case 'k':
140                 pwm_stop(0);
141                 break;
142         case 'l':
143                 pwm_start(0);
144                 break;
145         case 'n':
146                 if (pwm_freq_idx > 0) {
147                         pwm_freq_idx--;
148                         pwm_stop(0);
149                         pwm_freq_set(0, pwm_freq[pwm_freq_idx]);
150                         pwm_start(0);
151                         pwm_duty_set_percent(0, 22);    /* 22% of 9.43uS = 2.07uS */
152                 }
153                 break;
154         case 'm':
155                 if (pwm_freq_idx < ARRAY_SIZE(pwm_freq)-1) {
156                         pwm_freq_idx++;
157                         pwm_stop(0);
158                         pwm_freq_set(0, pwm_freq[pwm_freq_idx]);
159                         pwm_start(0);
160                         pwm_duty_set_percent(0, 22);    /* 22% of 9.43uS = 2.07uS */
161                 }
162                 break;
163         case 'u':
164                 DEBUGPCRF("PA23 output high");
165                 AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, AT91C_PIO_PA23);
166                 AT91F_PIO_SetOutput(AT91C_BASE_PIOA, AT91C_PIO_PA23);
167                 break;
168         case 'y':
169                 DEBUGPCRF("PA23 output low");
170                 AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, AT91C_PIO_PA23);
171                 AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, AT91C_PIO_PA23);
172                 return 0;
173                 break;
174         case 't':
175                 DEBUGPCRF("PA23 PeriphA (PWM)");
176                 AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0, AT91C_PA23_PWM0);
177                 return 0;
178                 break;
179         case 'f':
180                 DEBUGPCRF("%sabling Force100ASK", force_100ask ? "Dis":"En");
181                 if (force_100ask) {
182                         force_100ask = 0;
183                         opcd_rc632_clear_bits(RAH, RC632_REG_TX_CONTROL,
184                                               RC632_TXCTRL_FORCE_100_ASK);
185                 } else {
186                         force_100ask = 1;
187                         opcd_rc632_set_bits(RAH, RC632_REG_TX_CONTROL,
188                                             RC632_TXCTRL_FORCE_100_ASK);
189                 }
190                 return 0;
191                 break;
192         case 'v':
193                 if (mod_conductance > 0) {
194                         mod_conductance--;
195                         opcd_rc632_reg_write(RAH, RC632_REG_MOD_CONDUCTANCE,
196                                              rsrel_table[mod_conductance]);
197                 }
198                 break;
199         case 'b':
200                 if (mod_conductance < 0x3f) {
201                         mod_conductance++;
202                         opcd_rc632_reg_write(RAH, RC632_REG_MOD_CONDUCTANCE,
203                                              rsrel_table[mod_conductance]);
204                 }
205                 break;
206         case 'g':
207                 if (cw_conductance > 0) {
208                         cw_conductance--;
209                         opcd_rc632_reg_write(RAH, RC632_REG_CW_CONDUCTANCE, 
210                                              rsrel_table[cw_conductance]);
211                 }
212                 break;
213         case 'h':
214                 if (cw_conductance < 0x3f) {
215                         cw_conductance++;
216                         opcd_rc632_reg_write(RAH, RC632_REG_CW_CONDUCTANCE, 
217                                              rsrel_table[cw_conductance]);
218                 }
219                 break;
220         case '?':
221                 help();
222                 return 0;
223                 break;
224         case '<':
225                 tc_cdiv_phase_inc();
226                 break;
227         case '>':
228                 tc_cdiv_phase_dec();
229                 break;
230         case '{':
231                 if (cdiv_idx > 0)
232                         cdiv_idx--;
233                 tc_cdiv_set_divider(cdivs[cdiv_idx]);
234                 break;
235         case '}':
236                 if (cdiv_idx < ARRAY_SIZE(cdivs)-1)
237                         cdiv_idx++;
238                 tc_cdiv_set_divider(cdivs[cdiv_idx]);
239                 break;
240 #ifdef SSC
241         case 's':
242                 ssc_rx_start();
243                 break;
244         case 'S':
245                 ssc_rx_stop();
246                 break;
247 #endif
248         default:
249                 return -EINVAL;
250         }
252         DEBUGPCR("pwm_freq=%u, duty_percent=%u, mod_cond=%u, cw_cond=%u tc_cdiv=%u", 
253                  pwm_freq[pwm_freq_idx], duty_percent, mod_conductance, cw_conductance,
254                  cdivs[cdiv_idx]);
255         
256         return 0;
260 void _main_func(void)
262         /* first we try to get rid of pending to-be-sent stuff */
263         usb_out_process();
265         /* next we deal with incoming reqyests from USB EP1 (OUT) */
266         usb_in_process();
268         /* try unthrottling sources since we now are [more] likely to
269          * have empty request contexts */
270         rc632_unthrottle();
271 #ifdef SSC
272         ssc_rx_unthrottle();
273 #endif
275         led_toggle(2);