1 |
633c646a
|
henryk
|
#include <AT91SAM7.h>
|
2 |
|
|
#include <FreeRTOS.h>
|
3 |
|
|
#include <task.h>
|
4 |
cb27c687
|
henryk
|
#include <semphr.h>
|
5 |
633c646a
|
henryk
|
#include <queue.h>
|
6 |
|
|
#include <USB-CDC.h>
|
7 |
|
|
#include <board.h>
|
8 |
6cc8228e
|
henryk
|
#include <compile.h>
|
9 |
8e4e27b8
|
henryk
|
#include <string.h>
|
10 |
633c646a
|
henryk
|
|
11 |
|
|
#include "env.h"
|
12 |
|
|
#include "cmd.h"
|
13 |
|
|
#include "openpicc.h"
|
14 |
|
|
#include "led.h"
|
15 |
948f16ee
|
henryk
|
#include "da.h"
|
16 |
ee1f0214
|
henryk
|
#include "adc.h"
|
17 |
f0c0bc64
|
henryk
|
#include "pll.h"
|
18 |
ee1f0214
|
henryk
|
#include "tc_cdiv.h"
|
19 |
3d0a9bd4
|
henryk
|
#include "tc_cdiv_sync.h"
|
20 |
|
|
#include "pio_irq.h"
|
21 |
ad5b96d5
|
henryk
|
#include "ssc.h"
|
22 |
6304718e
|
henryk
|
#include "clock_switch.h"
|
23 |
c63871ac
|
henryk
|
#include "usb_print.h"
|
24 |
61ae0602
|
henryk
|
#include "load_modulation.h"
|
25 |
3ee3c4a6
|
henryk
|
#include "tc_sniffer.h"
|
26 |
6b18612b
|
henryk
|
#include "iso14443a_pretender.h"
|
27 |
633c646a
|
henryk
|
|
28 |
|
|
xQueueHandle xCmdQueue;
|
29 |
|
|
xTaskHandle xCmdTask;
|
30 |
|
|
xTaskHandle xCmdRecvUsbTask;
|
31 |
cb27c687
|
henryk
|
xTaskHandle xFieldMeterTask;
|
32 |
|
|
xSemaphoreHandle xFieldMeterMutex;
|
33 |
633c646a
|
henryk
|
|
34 |
2bf5a3ae
|
henryk
|
volatile int fdt_offset=-20 -16; // -16 for the SSC Tx set to continous bug
|
35 |
61ae0602
|
henryk
|
volatile int load_mod_level_set=3;
|
36 |
|
|
|
37 |
16d42d5f
|
henryk
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
38 |
|
|
static signed portCHAR pcWriteBuffer[512];
|
39 |
|
|
#endif
|
40 |
|
|
|
41 |
8e4e27b8
|
henryk
|
/* Whether to require a colon (':') be typed before long commands, similar to e.g. vi
|
42 |
|
|
* This makes a distinction between long commands and short commands: long commands may be
|
43 |
|
|
* longer than one character and/or accept optional parameters, short commands are only one
|
44 |
|
|
* character with no arguments (typically some toggling command). Short commands execute
|
45 |
|
|
* immediately when the character is pressed, long commands must be completed with return.
|
46 |
|
|
* */
|
47 |
|
|
static const portBASE_TYPE USE_COLON_FOR_LONG_COMMANDS = 0;
|
48 |
|
|
/* When not USE_COLON_FOR_LONG_COMMANDS then short commands will be recognized by including
|
49 |
|
|
* their character in the string SHORT_COMMANDS
|
50 |
|
|
* */
|
51 |
3ee3c4a6
|
henryk
|
static const char *SHORT_COMMANDS = "!prc+-l?hq9fjka#i";
|
52 |
8e4e27b8
|
henryk
|
/* Note that the long/short command distinction only applies to the USB serial console
|
53 |
|
|
* */
|
54 |
|
|
|
55 |
633c646a
|
henryk
|
/**********************************************************************/
|
56 |
|
|
void DumpUIntToUSB(unsigned int data)
|
57 |
|
|
{
|
58 |
|
|
int i=0;
|
59 |
|
|
unsigned char buffer[10],*p=&buffer[sizeof(buffer)];
|
60 |
|
|
|
61 |
|
|
do {
|
62 |
|
|
*--p='0'+(unsigned char)(data%10);
|
63 |
|
|
data/=10;
|
64 |
|
|
i++;
|
65 |
|
|
} while(data);
|
66 |
|
|
|
67 |
|
|
while(i--)
|
68 |
c63871ac
|
henryk
|
usb_print_char(*p++);
|
69 |
633c646a
|
henryk
|
}
|
70 |
|
|
/**********************************************************************/
|
71 |
|
|
|
72 |
9cde1dd0
|
henryk
|
void DumpStringToUSB(const char* text)
|
73 |
633c646a
|
henryk
|
{
|
74 |
c63871ac
|
henryk
|
usb_print_string(text);
|
75 |
633c646a
|
henryk
|
}
|
76 |
|
|
/**********************************************************************/
|
77 |
|
|
|
78 |
|
|
static inline unsigned char HexChar(unsigned char nibble)
|
79 |
|
|
{
|
80 |
|
|
return nibble + ((nibble<0x0A) ? '0':('A'-0xA));
|
81 |
|
|
}
|
82 |
|
|
|
83 |
|
|
void DumpBufferToUSB(char* buffer, int len)
|
84 |
|
|
{
|
85 |
|
|
int i;
|
86 |
|
|
|
87 |
|
|
for(i=0; i<len; i++) {
|
88 |
c63871ac
|
henryk
|
usb_print_char(HexChar( *buffer >> 4));
|
89 |
|
|
usb_print_char(HexChar( *buffer++ & 0xf));
|
90 |
633c646a
|
henryk
|
}
|
91 |
|
|
}
|
92 |
|
|
/**********************************************************************/
|
93 |
|
|
|
94 |
619b96eb
|
henryk
|
void DumpTimeToUSB(long ticks)
|
95 |
|
|
{
|
96 |
|
|
int h, s, m, ms;
|
97 |
|
|
ms = ticks;
|
98 |
|
|
|
99 |
|
|
s=ms/1000;
|
100 |
|
|
ms%=1000;
|
101 |
|
|
h=s/3600;
|
102 |
|
|
s%=3600;
|
103 |
|
|
m=s/60;
|
104 |
|
|
s%=60;
|
105 |
|
|
DumpUIntToUSB(h);
|
106 |
|
|
DumpStringToUSB("h:");
|
107 |
|
|
if(m < 10) DumpStringToUSB("0");
|
108 |
|
|
DumpUIntToUSB(m);
|
109 |
|
|
DumpStringToUSB("m:");
|
110 |
|
|
if(s < 10) DumpStringToUSB("0");
|
111 |
|
|
DumpUIntToUSB(s);
|
112 |
|
|
DumpStringToUSB("s.");
|
113 |
|
|
if(ms < 10) DumpStringToUSB("0");
|
114 |
|
|
if(ms < 100) DumpStringToUSB("0");
|
115 |
|
|
DumpUIntToUSB(ms);
|
116 |
|
|
DumpStringToUSB("ms");
|
117 |
|
|
}
|
118 |
|
|
|
119 |
633c646a
|
henryk
|
/*
|
120 |
|
|
* Convert a string to an integer. Ignores leading spaces.
|
121 |
|
|
* Optionally returns a pointer to the end of the number in the string */
|
122 |
|
|
int atoiEx(const char * nptr, char * * eptr)
|
123 |
|
|
{
|
124 |
|
|
portBASE_TYPE sign = 1, i=0;
|
125 |
|
|
int curval = 0;
|
126 |
|
|
while(nptr[i] == ' ' && nptr[i] != 0) i++;
|
127 |
|
|
if(nptr[i] == 0) goto out;
|
128 |
|
|
if(nptr[i] == '-') {sign *= -1; i++; }
|
129 |
|
|
else if(nptr[i] == '+') { i++; }
|
130 |
|
|
while(nptr[i] != 0 && nptr[i] >= '0' && nptr[i] <= '9')
|
131 |
|
|
curval = curval * 10 + (nptr[i++] - '0');
|
132 |
|
|
|
133 |
|
|
out:
|
134 |
|
|
if(eptr != NULL) *eptr = (char*)nptr+i;
|
135 |
|
|
return sign * curval;
|
136 |
|
|
}
|
137 |
|
|
|
138 |
6b18612b
|
henryk
|
/* Common code between increment/decrement UID/nonce */
|
139 |
|
|
static int change_value( int(* const getter)(u_int8_t*, size_t), int(* const setter)(u_int8_t*, size_t),
|
140 |
|
|
const s_int32_t increment, const char *name )
|
141 |
|
|
{
|
142 |
|
|
u_int8_t uid[4];
|
143 |
|
|
int ret;
|
144 |
|
|
if( getter(uid, sizeof(uid)) >= 0) {
|
145 |
|
|
(*((u_int32_t*)uid)) += increment;
|
146 |
|
|
taskENTER_CRITICAL();
|
147 |
|
|
ret = setter(uid, sizeof(uid));
|
148 |
|
|
taskEXIT_CRITICAL();
|
149 |
|
|
if(ret < 0) {
|
150 |
|
|
DumpStringToUSB("Failed to set the ");
|
151 |
|
|
DumpStringToUSB(name);
|
152 |
|
|
DumpStringToUSB("\n\r");
|
153 |
|
|
} else {
|
154 |
|
|
DumpStringToUSB("Successfully set ");
|
155 |
|
|
DumpStringToUSB(name);
|
156 |
|
|
DumpStringToUSB(" to ");
|
157 |
|
|
DumpBufferToUSB((char*)uid, sizeof(uid));
|
158 |
|
|
DumpStringToUSB("\n\r");
|
159 |
|
|
}
|
160 |
|
|
} else {
|
161 |
|
|
DumpStringToUSB("Couldn't get ");
|
162 |
|
|
DumpStringToUSB(name);
|
163 |
|
|
DumpStringToUSB("\n\r");
|
164 |
|
|
ret = -1;
|
165 |
|
|
}
|
166 |
|
|
return ret;
|
167 |
|
|
}
|
168 |
|
|
|
169 |
ad5b96d5
|
henryk
|
#define DYNAMIC_PIN_PLL_LOCK 1
|
170 |
|
|
static struct { int pin; int dynpin; char * description; } PIO_PINS[] = {
|
171 |
|
|
{0,DYNAMIC_PIN_PLL_LOCK, "pll lock "},
|
172 |
|
|
{OPENPICC_PIO_FRAME,0, "frame start"},
|
173 |
3d0a9bd4
|
henryk
|
};
|
174 |
|
|
void print_pio(void)
|
175 |
|
|
{
|
176 |
|
|
int data = *AT91C_PIOA_PDSR;
|
177 |
|
|
unsigned int i;
|
178 |
|
|
DumpStringToUSB(
|
179 |
|
|
" *****************************************************\n\r"
|
180 |
|
|
" * Current PIO readings: *\n\r"
|
181 |
|
|
" *****************************************************\n\r"
|
182 |
|
|
" *\n\r");
|
183 |
|
|
for(i=0; i<sizeof(PIO_PINS)/sizeof(PIO_PINS[0]); i++) {
|
184 |
ad5b96d5
|
henryk
|
if(PIO_PINS[i].dynpin != 0) continue;
|
185 |
3d0a9bd4
|
henryk
|
DumpStringToUSB(" * ");
|
186 |
|
|
DumpStringToUSB(PIO_PINS[i].description);
|
187 |
|
|
DumpStringToUSB(": ");
|
188 |
|
|
DumpUIntToUSB((data & PIO_PINS[i].pin) ? 1 : 0 );
|
189 |
|
|
DumpStringToUSB("\n\r");
|
190 |
|
|
}
|
191 |
|
|
DumpStringToUSB(" *****************************************************\n\r");
|
192 |
|
|
}
|
193 |
|
|
|
194 |
8c1bae59
|
henryk
|
|
195 |
633c646a
|
henryk
|
static const AT91PS_SPI spi = AT91C_BASE_SPI;
|
196 |
|
|
#define SPI_MAX_XFER_LEN 33
|
197 |
|
|
|
198 |
ad5b96d5
|
henryk
|
static int clock_select=0;
|
199 |
cb27c687
|
henryk
|
void startstop_field_meter(void);
|
200 |
633c646a
|
henryk
|
extern volatile unsigned portLONG ulCriticalNesting;
|
201 |
|
|
void prvExecCommand(u_int32_t cmd, portCHAR *args) {
|
202 |
|
|
static int led = 0;
|
203 |
|
|
portCHAR cByte = cmd & 0xff;
|
204 |
619b96eb
|
henryk
|
int i,ms;
|
205 |
633c646a
|
henryk
|
if(cByte>='A' && cByte<='Z')
|
206 |
|
|
cByte-=('A'-'a');
|
207 |
|
|
|
208 |
|
|
DumpStringToUSB("Got command ");
|
209 |
|
|
DumpUIntToUSB(cmd);
|
210 |
|
|
DumpStringToUSB(" with args ");
|
211 |
|
|
DumpStringToUSB(args);
|
212 |
|
|
DumpStringToUSB("\n\r");
|
213 |
|
|
|
214 |
|
|
i=0;
|
215 |
|
|
// Note: Commands have been uppercased when this code is called
|
216 |
|
|
switch(cmd)
|
217 |
|
|
{
|
218 |
ad5b96d5
|
henryk
|
case 'THRU': {
|
219 |
|
|
/*char buffer[64];
|
220 |
|
|
memset(buffer, 'A', sizeof(buffer));
|
221 |
|
|
usb_print_flush();
|
222 |
|
|
while(1) usb_print_buffer(buffer, 0, sizeof(buffer));*/
|
223 |
|
|
while(1) vUSBSendBuffer((unsigned char*)"AAAAAABCDEBBBBB", 0, 15);
|
224 |
|
|
}
|
225 |
|
|
break;
|
226 |
3d0a9bd4
|
henryk
|
case 'Z':
|
227 |
|
|
i=atoiEx(args, &args);
|
228 |
|
|
if(i==0) {
|
229 |
|
|
tc_cdiv_sync_disable();
|
230 |
|
|
DumpStringToUSB("cdiv_sync disabled \n\r");
|
231 |
|
|
} else {
|
232 |
|
|
tc_cdiv_sync_enable();
|
233 |
|
|
DumpStringToUSB("cdiv_sync enabled \n\r");
|
234 |
|
|
}
|
235 |
|
|
break;
|
236 |
021f7363
|
henryk
|
case 'G':
|
237 |
a72e0c20
|
henryk
|
if(!OPENPICC->features.data_gating) {
|
238 |
|
|
DumpStringToUSB("This hardware does not have data gating capability\n\r");
|
239 |
|
|
break;
|
240 |
|
|
}
|
241 |
021f7363
|
henryk
|
i=atoiEx(args, &args);
|
242 |
d3bab6e9
|
henryk
|
ssc_set_gate(i);
|
243 |
021f7363
|
henryk
|
if(i==0) {
|
244 |
a72e0c20
|
henryk
|
DumpStringToUSB("SSC_DATA disabled \n\r");
|
245 |
021f7363
|
henryk
|
} else {
|
246 |
a72e0c20
|
henryk
|
DumpStringToUSB("SSC_DATA enabled \n\r");
|
247 |
021f7363
|
henryk
|
}
|
248 |
|
|
break;
|
249 |
5cc0ed49
|
henryk
|
case 'D':
|
250 |
|
|
i=atoiEx(args, &args);
|
251 |
|
|
tc_cdiv_set_divider(i);
|
252 |
|
|
DumpStringToUSB("tc_cdiv set to ");
|
253 |
|
|
DumpUIntToUSB(i);
|
254 |
|
|
DumpStringToUSB("\n\r");
|
255 |
|
|
break;
|
256 |
3d0a9bd4
|
henryk
|
case 'P':
|
257 |
|
|
print_pio();
|
258 |
|
|
break;
|
259 |
e2e37bea
|
henryk
|
/* case 'R':
|
260 |
3ee3c4a6
|
henryk
|
start_stop_sniffing();
|
261 |
e2e37bea
|
henryk
|
break;*/
|
262 |
633c646a
|
henryk
|
case 'C':
|
263 |
|
|
DumpStringToUSB(
|
264 |
|
|
" *****************************************************\n\r"
|
265 |
|
|
" * Current configuration: *\n\r"
|
266 |
|
|
" *****************************************************\n\r"
|
267 |
6cc8228e
|
henryk
|
" * Version " COMPILE_SVNREV "\n\r"
|
268 |
|
|
" * compiled " COMPILE_DATE " by " COMPILE_BY "\n\r"
|
269 |
a72e0c20
|
henryk
|
" * running on ");
|
270 |
|
|
DumpStringToUSB(OPENPICC->release_name);
|
271 |
|
|
DumpStringToUSB("\n\r *\n\r");
|
272 |
633c646a
|
henryk
|
DumpStringToUSB(" * Uptime is ");
|
273 |
619b96eb
|
henryk
|
ms=xTaskGetTickCount();
|
274 |
|
|
DumpTimeToUSB(ms);
|
275 |
633c646a
|
henryk
|
DumpStringToUSB("\n\r");
|
276 |
948f16ee
|
henryk
|
DumpStringToUSB(" * The comparator threshold is ");
|
277 |
|
|
DumpUIntToUSB(da_get_value());
|
278 |
|
|
DumpStringToUSB("\n\r");
|
279 |
3d0a9bd4
|
henryk
|
DumpStringToUSB(" * Number of PIO IRQs handled: ");
|
280 |
|
|
i = pio_irq_get_count() & (~(unsigned int)0);
|
281 |
|
|
DumpUIntToUSB(i);
|
282 |
|
|
DumpStringToUSB("\n\r");
|
283 |
ee1f0214
|
henryk
|
DumpStringToUSB(" * current field strength: ");
|
284 |
|
|
DumpUIntToUSB(adc_get_field_strength());
|
285 |
|
|
DumpStringToUSB("\n\r");
|
286 |
61ae0602
|
henryk
|
DumpStringToUSB(" * fdt_offset: ");
|
287 |
|
|
if(fdt_offset < 0) {
|
288 |
|
|
DumpStringToUSB("-");
|
289 |
|
|
DumpUIntToUSB(-fdt_offset);
|
290 |
|
|
} else DumpUIntToUSB(fdt_offset);
|
291 |
|
|
DumpStringToUSB("\n\r");
|
292 |
|
|
DumpStringToUSB(" * load_mod_level: ");
|
293 |
|
|
DumpUIntToUSB(load_mod_level_set);
|
294 |
|
|
DumpStringToUSB("\n\r");
|
295 |
8c1bae59
|
henryk
|
DumpStringToUSB(" * SSC performance metrics:\n\r");
|
296 |
ad5b96d5
|
henryk
|
for(i=0; i<_MAX_METRICS; i++) {
|
297 |
|
|
char *name;
|
298 |
|
|
int value;
|
299 |
|
|
if(ssc_get_metric(i, &name, &value)) {
|
300 |
|
|
DumpStringToUSB(" * \t");
|
301 |
|
|
DumpStringToUSB(name);
|
302 |
|
|
DumpStringToUSB(": ");
|
303 |
|
|
DumpUIntToUSB(value);
|
304 |
|
|
DumpStringToUSB("\n\r");
|
305 |
|
|
}
|
306 |
8c1bae59
|
henryk
|
}
|
307 |
5cc0ed49
|
henryk
|
DumpStringToUSB(" * SSC status: ");
|
308 |
|
|
DumpUIntToUSB(AT91C_BASE_SSC->SSC_SR);
|
309 |
062f55ca
|
henryk
|
DumpStringToUSB("\n\r");
|
310 |
|
|
DumpStringToUSB(" * TC0_CV value: ");
|
311 |
|
|
DumpUIntToUSB(*AT91C_TC0_CV);
|
312 |
|
|
DumpStringToUSB("\n\r");
|
313 |
ad5b96d5
|
henryk
|
DumpStringToUSB(" * TC2_CV value: ");
|
314 |
|
|
DumpUIntToUSB(*AT91C_TC2_CV);
|
315 |
|
|
DumpStringToUSB("\n\r");
|
316 |
|
|
DumpStringToUSB(" * TC2_IMR value: ");
|
317 |
|
|
DumpUIntToUSB(*AT91C_TC2_IMR);
|
318 |
|
|
DumpStringToUSB("\n\r");
|
319 |
|
|
DumpStringToUSB(" * TC2_SR value: ");
|
320 |
|
|
DumpUIntToUSB(*AT91C_TC2_SR);
|
321 |
|
|
DumpStringToUSB("\n\r");
|
322 |
|
|
DumpStringToUSB(" * TC2_RB value: ");
|
323 |
|
|
DumpUIntToUSB(*AT91C_TC2_RB);
|
324 |
|
|
DumpStringToUSB("\n\r");
|
325 |
|
|
DumpStringToUSB(" * TC2_RC value: ");
|
326 |
|
|
DumpUIntToUSB(*AT91C_TC2_RC);
|
327 |
|
|
DumpStringToUSB("\n\r");
|
328 |
48c311bd
|
henryk
|
DumpStringToUSB(" * SSC_SR value: ");
|
329 |
|
|
DumpUIntToUSB(*AT91C_SSC_SR);
|
330 |
|
|
DumpStringToUSB("\n\r");
|
331 |
062f55ca
|
henryk
|
DumpStringToUSB(" * SSC_RCMR value: ");
|
332 |
|
|
DumpUIntToUSB(*AT91C_SSC_RCMR);
|
333 |
|
|
DumpStringToUSB("\n\r");
|
334 |
48c311bd
|
henryk
|
DumpStringToUSB(" * SSC_TCMR value: ");
|
335 |
|
|
DumpUIntToUSB(*AT91C_SSC_TCMR);
|
336 |
|
|
DumpStringToUSB("\n\r");
|
337 |
|
|
DumpStringToUSB(" * SSC_TFMR value: ");
|
338 |
|
|
DumpUIntToUSB(*AT91C_SSC_TFMR);
|
339 |
|
|
DumpStringToUSB("\n\r");
|
340 |
|
|
DumpStringToUSB(" * SSC_TPR value: ");
|
341 |
|
|
DumpUIntToUSB(*AT91C_SSC_TPR);
|
342 |
|
|
DumpStringToUSB("\n\r");
|
343 |
|
|
DumpStringToUSB(" * SSC_TCR value: ");
|
344 |
|
|
DumpUIntToUSB(*AT91C_SSC_TCR);
|
345 |
|
|
DumpStringToUSB("\n\r");
|
346 |
ad5b96d5
|
henryk
|
DumpStringToUSB(" * SSC_RPR value: ");
|
347 |
|
|
DumpUIntToUSB(*AT91C_SSC_RPR);
|
348 |
|
|
DumpStringToUSB("\n\r");
|
349 |
|
|
DumpStringToUSB(" * SSC_RCR value: ");
|
350 |
|
|
DumpUIntToUSB(*AT91C_SSC_RCR);
|
351 |
|
|
DumpStringToUSB("\n\r");
|
352 |
ba63352b
|
henryk
|
DumpStringToUSB(" * SSC_IMR value: ");
|
353 |
|
|
DumpUIntToUSB(*AT91C_SSC_IMR);
|
354 |
|
|
DumpStringToUSB("\n\r");
|
355 |
633c646a
|
henryk
|
DumpStringToUSB(
|
356 |
|
|
" *\n\r"
|
357 |
|
|
" *****************************************************\n\r"
|
358 |
|
|
);
|
359 |
|
|
break;
|
360 |
|
|
case '+':
|
361 |
|
|
case '-':
|
362 |
|
|
if(cmd == '+')
|
363 |
|
|
{
|
364 |
948f16ee
|
henryk
|
if(da_get_value() < 255)
|
365 |
|
|
da_comp_carr(da_get_value()+1);
|
366 |
633c646a
|
henryk
|
}
|
367 |
|
|
else
|
368 |
948f16ee
|
henryk
|
if(da_get_value() > 0)
|
369 |
|
|
da_comp_carr(da_get_value()-1);;
|
370 |
633c646a
|
henryk
|
|
371 |
948f16ee
|
henryk
|
DumpStringToUSB(" * Comparator threshold set to ");
|
372 |
|
|
DumpUIntToUSB(da_get_value());
|
373 |
|
|
DumpStringToUSB("\n\r");
|
374 |
633c646a
|
henryk
|
break;
|
375 |
6b18612b
|
henryk
|
case 'U+':
|
376 |
|
|
i=atoiEx(args, &args);
|
377 |
|
|
change_value(get_UID, set_UID, i==0 ? +1 : +i , "UID"); break;
|
378 |
|
|
case 'U-':
|
379 |
|
|
i=atoiEx(args, &args);
|
380 |
|
|
change_value(get_UID, set_UID, i==0 ? -1 : -i , "UID"); break;
|
381 |
|
|
case 'N+':
|
382 |
|
|
i=atoiEx(args, &args);
|
383 |
|
|
change_value(get_nonce, set_nonce, i==0 ? +1 : +i, "nonce"); break;
|
384 |
|
|
case 'N-':
|
385 |
|
|
i=atoiEx(args, &args);
|
386 |
|
|
change_value(get_nonce, set_nonce, i==0 ? -1 : -i, "nonce"); break;
|
387 |
633c646a
|
henryk
|
case 'L':
|
388 |
|
|
led = (led+1)%4;
|
389 |
|
|
vLedSetRed( (led&1) );
|
390 |
|
|
vLedSetGreen( led&2 );
|
391 |
|
|
DumpStringToUSB(" * LEDs set to ");
|
392 |
|
|
vUSBSendByte( (char)led + '0' );
|
393 |
|
|
DumpStringToUSB("\n\r");
|
394 |
|
|
break;
|
395 |
3fb02f71
|
henryk
|
case '!':
|
396 |
|
|
tc_cdiv_sync_reset();
|
397 |
|
|
break;
|
398 |
ad5b96d5
|
henryk
|
case '#':
|
399 |
|
|
if(!OPENPICC->features.clock_switching) {
|
400 |
|
|
DumpStringToUSB("* This hardware is not clock switching capable\n\r");
|
401 |
|
|
break;
|
402 |
|
|
}
|
403 |
6304718e
|
henryk
|
clock_select = (clock_select+1) % 2;
|
404 |
|
|
clock_switch(clock_select);
|
405 |
ad5b96d5
|
henryk
|
DumpStringToUSB("Active clock is now ");
|
406 |
|
|
DumpUIntToUSB(clock_select);
|
407 |
|
|
DumpStringToUSB("\n\r");
|
408 |
|
|
break;
|
409 |
61ae0602
|
henryk
|
case 'J':
|
410 |
|
|
fdt_offset++;
|
411 |
|
|
DumpStringToUSB("fdt_offset is now ");
|
412 |
|
|
if(fdt_offset<0) { DumpStringToUSB("-"); DumpUIntToUSB(-fdt_offset); }
|
413 |
|
|
else { DumpStringToUSB("+"); DumpUIntToUSB(fdt_offset); }
|
414 |
|
|
DumpStringToUSB("\n\r");
|
415 |
|
|
break;
|
416 |
|
|
case 'K':
|
417 |
|
|
fdt_offset--;
|
418 |
|
|
DumpStringToUSB("fdt_offset is now ");
|
419 |
|
|
if(fdt_offset<0) { DumpStringToUSB("-"); DumpUIntToUSB(-fdt_offset); }
|
420 |
|
|
else { DumpStringToUSB("+"); DumpUIntToUSB(fdt_offset); }
|
421 |
|
|
DumpStringToUSB("\n\r");
|
422 |
|
|
break;
|
423 |
cb27c687
|
henryk
|
case 'F':
|
424 |
|
|
startstop_field_meter();
|
425 |
16d42d5f
|
henryk
|
break;
|
426 |
f0c0bc64
|
henryk
|
case 'I':
|
427 |
|
|
pll_inhibit(!pll_is_inhibited());
|
428 |
|
|
if(pll_is_inhibited()) DumpStringToUSB(" * PLL is now inhibited\n\r");
|
429 |
|
|
else DumpStringToUSB(" * PLL is now running\n\r");
|
430 |
16d42d5f
|
henryk
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
431 |
|
|
case 'T':
|
432 |
|
|
memset(pcWriteBuffer, 0, sizeof(pcWriteBuffer));
|
433 |
|
|
vTaskList(pcWriteBuffer);
|
434 |
|
|
DumpStringToUSB((char*)pcWriteBuffer);
|
435 |
|
|
break;
|
436 |
|
|
#endif
|
437 |
6cc8228e
|
henryk
|
case 'Q':
|
438 |
ad5b96d5
|
henryk
|
//BROKEN new ssc code
|
439 |
|
|
//ssc_rx_start();
|
440 |
6cc8228e
|
henryk
|
while(0) {
|
441 |
|
|
DumpUIntToUSB(AT91C_BASE_SSC->SSC_SR);
|
442 |
|
|
DumpStringToUSB("\n\r");
|
443 |
|
|
}
|
444 |
|
|
break;
|
445 |
61ae0602
|
henryk
|
case 'A':
|
446 |
|
|
load_mod_level_set = (load_mod_level_set+1) % 4;
|
447 |
|
|
load_mod_level(load_mod_level_set);
|
448 |
|
|
DumpStringToUSB("load_mod_level is now ");
|
449 |
|
|
DumpUIntToUSB(load_mod_level_set);
|
450 |
|
|
DumpStringToUSB("\n\r");
|
451 |
|
|
break;
|
452 |
633c646a
|
henryk
|
case 'H':
|
453 |
|
|
case '?':
|
454 |
|
|
DumpStringToUSB(
|
455 |
|
|
" *****************************************************\n\r"
|
456 |
|
|
" * OpenPICC USB terminal *\n\r"
|
457 |
|
|
" * (C) 2007 Milosch Meriac <meriac@openbeacon.de> *\n\r"
|
458 |
|
|
" * (C) 2007 Henryk Plötz <henryk@ploetzli.ch> *\n\r"
|
459 |
|
|
" *****************************************************\n\r"
|
460 |
6cc8228e
|
henryk
|
" * Version " COMPILE_SVNREV "\n\r"
|
461 |
|
|
" * compiled " COMPILE_DATE " by " COMPILE_BY "\n\r"
|
462 |
a72e0c20
|
henryk
|
" * running on ");
|
463 |
|
|
DumpStringToUSB(OPENPICC->release_name);
|
464 |
|
|
DumpStringToUSB("\n\r *\n\r"
|
465 |
ad5b96d5
|
henryk
|
" * thru - test throughput\n\r"
|
466 |
16d42d5f
|
henryk
|
#if ( configUSE_TRACE_FACILITY == 1 )
|
467 |
|
|
" * t - print task list and stack usage\n\r"
|
468 |
|
|
#endif
|
469 |
633c646a
|
henryk
|
" * c - print configuration\n\r"
|
470 |
948f16ee
|
henryk
|
" * +,- - decrease/increase comparator threshold\n\r"
|
471 |
ad5b96d5
|
henryk
|
" * # - switch clock\n\r"
|
472 |
633c646a
|
henryk
|
" * l - cycle LEDs\n\r"
|
473 |
3d0a9bd4
|
henryk
|
" * p - print PIO pins\n\r"
|
474 |
3ee3c4a6
|
henryk
|
" * r - start/stop receiving\n\r"
|
475 |
3d0a9bd4
|
henryk
|
" * z 0/1- enable or disable tc_cdiv_sync\n\r"
|
476 |
f0c0bc64
|
henryk
|
" * i - inhibit/uninhibit PLL\n\r"
|
477 |
3fb02f71
|
henryk
|
" * ! - reset tc_cdiv_sync\n\r"
|
478 |
6cc8228e
|
henryk
|
" * q - start rx\n\r"
|
479 |
cb27c687
|
henryk
|
" * f - start/stop field meter\n\r"
|
480 |
5cc0ed49
|
henryk
|
" * d div- set tc_cdiv divider value 16, 32, 64, ...\n\r"
|
481 |
61ae0602
|
henryk
|
" * j,k - increase, decrease fdt_offset\n\r"
|
482 |
|
|
" * a - change load modulation level\n\r"
|
483 |
021f7363
|
henryk
|
" * g 0/1- disable or enable SSC_DATA through gate\n\r"
|
484 |
6cc8228e
|
henryk
|
" * 9 - reset CPU\n\r"
|
485 |
633c646a
|
henryk
|
" * ?,h - display this help screen\n\r"
|
486 |
|
|
" *\n\r"
|
487 |
|
|
" *****************************************************\n\r"
|
488 |
|
|
);
|
489 |
|
|
break;
|
490 |
6cc8228e
|
henryk
|
case '9':
|
491 |
|
|
AT91F_RSTSoftReset(AT91C_BASE_RSTC, AT91C_RSTC_PROCRST|
|
492 |
|
|
AT91C_RSTC_PERRST|AT91C_RSTC_EXTRST);
|
493 |
|
|
break;
|
494 |
633c646a
|
henryk
|
}
|
495 |
|
|
|
496 |
|
|
}
|
497 |
|
|
|
498 |
|
|
// A task to execute commands
|
499 |
|
|
void vCmdCode(void *pvParameters) {
|
500 |
|
|
(void) pvParameters;
|
501 |
|
|
u_int32_t cmd;
|
502 |
|
|
portBASE_TYPE i, j=0;
|
503 |
|
|
|
504 |
|
|
for(;;) {
|
505 |
|
|
cmd_type next_command;
|
506 |
|
|
cmd = j = 0;
|
507 |
|
|
if( xQueueReceive(xCmdQueue, &next_command, ( portTickType ) 100 ) ) {
|
508 |
|
|
DumpStringToUSB("Command received:");
|
509 |
|
|
DumpStringToUSB(next_command.command);
|
510 |
|
|
DumpStringToUSB("\n\r");
|
511 |
|
|
while(next_command.command[j] == ' ' && next_command.command[j] != 0) {
|
512 |
|
|
j++;
|
513 |
|
|
}
|
514 |
|
|
for(i=0;i<4;i++) {
|
515 |
|
|
portCHAR cByte = next_command.command[i+j];
|
516 |
|
|
if(next_command.command[i+j] == 0 || next_command.command[i+j] == ' ')
|
517 |
|
|
break;
|
518 |
|
|
if(cByte>='a' && cByte<='z') {
|
519 |
|
|
cmd = (cmd<<8) | (cByte+('A'-'a'));
|
520 |
|
|
} else cmd = (cmd<<8) | cByte;
|
521 |
|
|
}
|
522 |
|
|
while(next_command.command[i+j] == ' ' && next_command.command[i+j] != 0) {
|
523 |
|
|
i++;
|
524 |
|
|
}
|
525 |
|
|
prvExecCommand(cmd, next_command.command+i+j);
|
526 |
|
|
} else {
|
527 |
|
|
}
|
528 |
|
|
}
|
529 |
|
|
}
|
530 |
|
|
|
531 |
8e4e27b8
|
henryk
|
|
532 |
|
|
|
533 |
633c646a
|
henryk
|
// A task to read commands from USB
|
534 |
|
|
void vCmdRecvUsbCode(void *pvParameters) {
|
535 |
|
|
portBASE_TYPE len=0;
|
536 |
8e4e27b8
|
henryk
|
portBASE_TYPE short_command=1, submit_it=0;
|
537 |
633c646a
|
henryk
|
cmd_type next_command = { source: SRC_USB, command: ""};
|
538 |
|
|
(void) pvParameters;
|
539 |
|
|
|
540 |
|
|
for( ;; ) {
|
541 |
|
|
if(vUSBRecvByte(&next_command.command[len], 1, 100)) {
|
542 |
8e4e27b8
|
henryk
|
if(USE_COLON_FOR_LONG_COMMANDS) {
|
543 |
|
|
if(len == 0 && next_command.command[len] == ':')
|
544 |
|
|
short_command = 0;
|
545 |
|
|
} else {
|
546 |
|
|
if(strchr(SHORT_COMMANDS, next_command.command[len]) == NULL)
|
547 |
|
|
short_command = 0;
|
548 |
|
|
}
|
549 |
633c646a
|
henryk
|
next_command.command[len+1] = 0;
|
550 |
|
|
DumpStringToUSB(next_command.command + len);
|
551 |
|
|
if(next_command.command[len] == '\n' || next_command.command[len] == '\r') {
|
552 |
|
|
next_command.command[len] = 0;
|
553 |
8e4e27b8
|
henryk
|
submit_it = 1;
|
554 |
|
|
}
|
555 |
|
|
if(short_command==1) {
|
556 |
|
|
submit_it = 1;
|
557 |
|
|
}
|
558 |
|
|
if(submit_it) {
|
559 |
|
|
if(len > 0 || short_command) {
|
560 |
633c646a
|
henryk
|
if( xQueueSend(xCmdQueue, &next_command, 0) != pdTRUE) {
|
561 |
|
|
DumpStringToUSB("Queue full, command can't be processed.\n");
|
562 |
|
|
}
|
563 |
|
|
}
|
564 |
8e4e27b8
|
henryk
|
len=0;
|
565 |
|
|
submit_it=0;
|
566 |
|
|
short_command=1;
|
567 |
|
|
} else if( len>0 || next_command.command[len] != ':') len++;
|
568 |
633c646a
|
henryk
|
if(len >= MAX_CMD_LEN-1) {
|
569 |
|
|
DumpStringToUSB("ERROR: Command too long. Ignored.");
|
570 |
|
|
len=0;
|
571 |
|
|
}
|
572 |
|
|
}
|
573 |
|
|
}
|
574 |
|
|
}
|
575 |
|
|
|
576 |
cb27c687
|
henryk
|
static portBASE_TYPE field_meter_enabled = 0;
|
577 |
|
|
#define FIELD_METER_WIDTH 80
|
578 |
|
|
#define FIELD_METER_MAX_VALUE 160
|
579 |
81d6f890
|
henryk
|
#define FIELD_METER_SCALE_FACTOR (FIELD_METER_MAX_VALUE/FIELD_METER_WIDTH)
|
580 |
cb27c687
|
henryk
|
// A task to print the field strength as a bar graph
|
581 |
|
|
void vFieldMeter(void *pvParameters) {
|
582 |
|
|
(void) pvParameters;
|
583 |
|
|
char meter_string[FIELD_METER_WIDTH+2];
|
584 |
|
|
|
585 |
|
|
while(1) {
|
586 |
|
|
if(xSemaphoreTake(xFieldMeterMutex, portMAX_DELAY)) {
|
587 |
|
|
int i,ad_value = adc_get_field_strength();
|
588 |
|
|
meter_string[0] = '\r';
|
589 |
|
|
|
590 |
|
|
for(i=0; i<FIELD_METER_WIDTH; i++)
|
591 |
|
|
meter_string[i+1] =
|
592 |
81d6f890
|
henryk
|
(ad_value / FIELD_METER_SCALE_FACTOR < i) ?
|
593 |
|
|
' ' :
|
594 |
|
|
((i*FIELD_METER_SCALE_FACTOR)%10==0 ?
|
595 |
|
|
(((i*FIELD_METER_SCALE_FACTOR)/10)%10)+'0' : '#' );
|
596 |
cb27c687
|
henryk
|
meter_string[i+1] = 0;
|
597 |
|
|
usb_print_string(meter_string);
|
598 |
|
|
|
599 |
|
|
vTaskDelay(100*portTICK_RATE_MS);
|
600 |
|
|
if(field_meter_enabled == 1) xSemaphoreGive(xFieldMeterMutex);
|
601 |
|
|
}
|
602 |
|
|
}
|
603 |
|
|
}
|
604 |
|
|
|
605 |
|
|
void startstop_field_meter(void) {
|
606 |
|
|
if(field_meter_enabled) {
|
607 |
|
|
field_meter_enabled = 0;
|
608 |
|
|
} else {
|
609 |
|
|
field_meter_enabled = 1;
|
610 |
|
|
xSemaphoreGive(xFieldMeterMutex);
|
611 |
|
|
}
|
612 |
|
|
}
|
613 |
|
|
|
614 |
a72e0c20
|
henryk
|
portBASE_TYPE vCmdInit() {
|
615 |
|
|
unsigned int i;
|
616 |
|
|
for(i=0; i<sizeof(PIO_PINS)/sizeof(PIO_PINS[0]); i++) {
|
617 |
ad5b96d5
|
henryk
|
if(PIO_PINS[i].dynpin == DYNAMIC_PIN_PLL_LOCK) {
|
618 |
a72e0c20
|
henryk
|
PIO_PINS[i].pin = OPENPICC->PLL_LOCK;
|
619 |
ad5b96d5
|
henryk
|
PIO_PINS[i].dynpin = 0;
|
620 |
a72e0c20
|
henryk
|
}
|
621 |
|
|
}
|
622 |
|
|
|
623 |
633c646a
|
henryk
|
/* FIXME Maybe modify to use pointers? */
|
624 |
|
|
xCmdQueue = xQueueCreate( 10, sizeof(cmd_type) );
|
625 |
|
|
if(xCmdQueue == 0) {
|
626 |
|
|
return 0;
|
627 |
|
|
}
|
628 |
cb27c687
|
henryk
|
vSemaphoreCreateBinary( xFieldMeterMutex );
|
629 |
|
|
if(xFieldMeterMutex == 0) {
|
630 |
|
|
return 0;
|
631 |
|
|
}
|
632 |
|
|
xSemaphoreTake(xFieldMeterMutex, portMAX_DELAY);
|
633 |
|
|
|
634 |
633c646a
|
henryk
|
if(xTaskCreate(vCmdCode, (signed portCHAR *)"CMD", TASK_CMD_STACK, NULL,
|
635 |
|
|
TASK_CMD_PRIORITY, &xCmdTask) != pdPASS) {
|
636 |
|
|
return 0;
|
637 |
|
|
}
|
638 |
|
|
|
639 |
16d42d5f
|
henryk
|
if(xTaskCreate(vCmdRecvUsbCode, (signed portCHAR *)"CMDUSB", 128, NULL,
|
640 |
633c646a
|
henryk
|
TASK_CMD_PRIORITY, &xCmdRecvUsbTask) != pdPASS) {
|
641 |
|
|
return 0;
|
642 |
|
|
}
|
643 |
|
|
|
644 |
16d42d5f
|
henryk
|
if(xTaskCreate(vFieldMeter, (signed portCHAR *)"FIELD METER", 128, NULL,
|
645 |
cb27c687
|
henryk
|
TASK_CMD_PRIORITY, &xFieldMeterTask) != pdPASS) {
|
646 |
|
|
return 0;
|
647 |
|
|
}
|
648 |
|
|
|
649 |
633c646a
|
henryk
|
return 1;
|
650 |
|
|
}
|