Project

General

Profile

Download (18.8 KB) Statistics
| Branch: | Tag: | Revision:
1
#include <AT91SAM7.h>
2
#include <FreeRTOS.h>
3
#include <task.h>
4
#include <semphr.h>
5
#include <queue.h>
6
#include <USB-CDC.h>
7
#include <board.h>
8
#include <compile.h>
9
#include <string.h>
10

    
11
#include "env.h"
12
#include "cmd.h"
13
#include "openpicc.h"
14
#include "led.h"
15
#include "da.h"
16
#include "adc.h"
17
#include "pll.h"
18
#include "tc_cdiv.h"
19
#include "tc_cdiv_sync.h"
20
#include "pio_irq.h"
21
#include "ssc.h"
22
#include "clock_switch.h"
23
#include "usb_print.h"
24
#include "load_modulation.h"
25
#include "tc_sniffer.h"
26
#include "iso14443a_pretender.h"
27

    
28
xQueueHandle xCmdQueue;
29
xTaskHandle xCmdTask;
30
xTaskHandle xCmdRecvUsbTask;
31
xTaskHandle xFieldMeterTask;
32
xSemaphoreHandle xFieldMeterMutex;
33

    
34
volatile int fdt_offset=-20  -16; // -16 for the SSC Tx set to continous bug
35
volatile int load_mod_level_set=3;
36

    
37
#if ( configUSE_TRACE_FACILITY == 1 )
38
static signed portCHAR pcWriteBuffer[512];
39
#endif
40

    
41
/* 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
static const char *SHORT_COMMANDS = "!prc+-l?hq9fjka#i";
52
/* Note that the long/short command distinction only applies to the USB serial console
53
 * */
54

    
55
/**********************************************************************/
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
        usb_print_char(*p++);
69
}
70
/**********************************************************************/
71

    
72
void DumpStringToUSB(const char* text)
73
{
74
    usb_print_string(text);
75
}
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
	usb_print_char(HexChar( *buffer  >>   4));
89
	usb_print_char(HexChar( *buffer++ & 0xf));
90
    }
91
}
92
/**********************************************************************/
93

    
94
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
/*
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
/* 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
#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
};
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
			if(PIO_PINS[i].dynpin != 0) continue;
185
        	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

    
195
static const AT91PS_SPI spi = AT91C_BASE_SPI;
196
#define SPI_MAX_XFER_LEN 33
197

    
198
static int clock_select=0;
199
void startstop_field_meter(void);
200
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
	int i,ms;
205
	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
		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
		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
		case 'G':
237
			if(!OPENPICC->features.data_gating) {
238
				DumpStringToUSB("This hardware does not have data gating capability\n\r");
239
				break;
240
			}
241
		    i=atoiEx(args, &args);
242
		    ssc_set_gate(i);
243
		    if(i==0) {
244
		    	DumpStringToUSB("SSC_DATA disabled \n\r");
245
		    } else {
246
		    	DumpStringToUSB("SSC_DATA enabled \n\r");
247
		    }
248
		    break;
249
		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
		case 'P':
257
		    print_pio();
258
		    break;
259
/*		case 'R':
260
			start_stop_sniffing();
261
			break;*/
262
		case 'C':
263
		    DumpStringToUSB(
264
			" *****************************************************\n\r"
265
			" * Current configuration:                            *\n\r"
266
			" *****************************************************\n\r"
267
			" * Version " COMPILE_SVNREV "\n\r"
268
			" * compiled " COMPILE_DATE " by " COMPILE_BY "\n\r"
269
			" * running on ");
270
		    DumpStringToUSB(OPENPICC->release_name);
271
		    DumpStringToUSB("\n\r *\n\r");
272
		    DumpStringToUSB(" * Uptime is ");
273
		    ms=xTaskGetTickCount();
274
		    DumpTimeToUSB(ms);
275
		    DumpStringToUSB("\n\r");
276
		    DumpStringToUSB(" * The comparator threshold is ");
277
		    DumpUIntToUSB(da_get_value());
278
		    DumpStringToUSB("\n\r");
279
		    DumpStringToUSB(" * Number of PIO IRQs handled: ");
280
		    i = pio_irq_get_count() & (~(unsigned int)0);
281
		    DumpUIntToUSB(i);
282
		    DumpStringToUSB("\n\r");
283
		    DumpStringToUSB(" * current field strength: ");
284
		    DumpUIntToUSB(adc_get_field_strength());
285
		    DumpStringToUSB("\n\r");
286
		    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
		    DumpStringToUSB(" * SSC performance metrics:\n\r");
296
		    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
		    }
307
		    DumpStringToUSB(" * SSC status: ");
308
		    DumpUIntToUSB(AT91C_BASE_SSC->SSC_SR);
309
		    DumpStringToUSB("\n\r");
310
		    DumpStringToUSB(" * TC0_CV value: ");
311
		    DumpUIntToUSB(*AT91C_TC0_CV);
312
		    DumpStringToUSB("\n\r");
313
		    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
		    DumpStringToUSB(" * SSC_SR value: ");
329
		    DumpUIntToUSB(*AT91C_SSC_SR);
330
		    DumpStringToUSB("\n\r");
331
		    DumpStringToUSB(" * SSC_RCMR value: ");
332
		    DumpUIntToUSB(*AT91C_SSC_RCMR);
333
		    DumpStringToUSB("\n\r");
334
		    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
		    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
		    DumpStringToUSB(" * SSC_IMR value: ");
353
		    DumpUIntToUSB(*AT91C_SSC_IMR);
354
		    DumpStringToUSB("\n\r");
355
		    DumpStringToUSB(
356
			" *\n\r"
357
			" *****************************************************\n\r"
358
			);
359
		    break;
360
		case '+':
361
		case '-':
362
		    if(cmd == '+')
363
		    {
364
			if(da_get_value() < 255)
365
			    da_comp_carr(da_get_value()+1);
366
		    }
367
		    else
368
			if(da_get_value() > 0)
369
			    da_comp_carr(da_get_value()-1);;
370
		    			
371
		    DumpStringToUSB(" * Comparator threshold set to ");
372
		    DumpUIntToUSB(da_get_value());		    
373
		    DumpStringToUSB("\n\r");
374
		    break;
375
		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
		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
		case '!':
396
		    tc_cdiv_sync_reset();
397
		    break;
398
		case '#':
399
			if(!OPENPICC->features.clock_switching) {
400
				DumpStringToUSB("* This hardware is not clock switching capable\n\r");
401
				break;
402
			}
403
			clock_select = (clock_select+1) % 2;
404
			clock_switch(clock_select);
405
			DumpStringToUSB("Active clock is now ");
406
			DumpUIntToUSB(clock_select);
407
			DumpStringToUSB("\n\r");
408
			break;
409
		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
		case 'F':
424
		    startstop_field_meter();
425
		    break;
426
		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
#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
		case 'Q':
438
		    //BROKEN new ssc code
439
			//ssc_rx_start();
440
		    while(0) {
441
		    	DumpUIntToUSB(AT91C_BASE_SSC->SSC_SR);
442
		    	DumpStringToUSB("\n\r");
443
		    }
444
		    break;
445
		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
		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
			" * Version " COMPILE_SVNREV "\n\r"
461
			" * compiled " COMPILE_DATE " by " COMPILE_BY "\n\r"
462
			" * running on ");
463
		    DumpStringToUSB(OPENPICC->release_name);
464
		    DumpStringToUSB("\n\r *\n\r"
465
		    " * thru - test throughput\n\r"
466
#if ( configUSE_TRACE_FACILITY == 1 )
467
			" * t    - print task list and stack usage\n\r"
468
#endif
469
			" * c    - print configuration\n\r"
470
			" * +,-  - decrease/increase comparator threshold\n\r"
471
		    " * #    - switch clock\n\r"
472
			" * l    - cycle LEDs\n\r"
473
			" * p    - print PIO pins\n\r"
474
		    " * r    - start/stop receiving\n\r"
475
			" * z 0/1- enable or disable tc_cdiv_sync\n\r"
476
			" * i    - inhibit/uninhibit PLL\n\r"
477
			" * !    - reset tc_cdiv_sync\n\r"
478
			" * q    - start rx\n\r"
479
			" * f    - start/stop field meter\n\r"
480
			" * d div- set tc_cdiv divider value 16, 32, 64, ...\n\r"
481
			" * j,k  - increase, decrease fdt_offset\n\r"
482
			" * a    - change load modulation level\n\r"
483
			" * g 0/1- disable or enable SSC_DATA through gate\n\r"
484
			" * 9    - reset CPU\n\r"
485
			" * ?,h  - display this help screen\n\r"
486
			" *\n\r"
487
			" *****************************************************\n\r"
488
			);
489
		    break;
490
		case '9':
491
		    AT91F_RSTSoftReset(AT91C_BASE_RSTC, AT91C_RSTC_PROCRST|
492
			AT91C_RSTC_PERRST|AT91C_RSTC_EXTRST);
493
		    break;
494
	    }
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

    
532

    
533
// A task to read commands from USB
534
void vCmdRecvUsbCode(void *pvParameters) {
535
	portBASE_TYPE len=0;
536
	portBASE_TYPE short_command=1, submit_it=0;
537
	cmd_type next_command = { source: SRC_USB, command: ""};
538
	(void) pvParameters;
539
    
540
	for( ;; ) {
541
		if(vUSBRecvByte(&next_command.command[len], 1, 100)) {
542
			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
			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
				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
			    		if( xQueueSend(xCmdQueue, &next_command, 0) != pdTRUE) {
561
			    			DumpStringToUSB("Queue full, command can't be processed.\n");
562
			    		}
563
				}
564
		    		len=0;
565
		    		submit_it=0;
566
		    		short_command=1;
567
			} else if( len>0 || next_command.command[len] != ':') len++;
568
			if(len >= MAX_CMD_LEN-1) {
569
				DumpStringToUSB("ERROR: Command too long. Ignored.");
570
				len=0;
571
			}
572
	    	}
573
    	}
574
}
575

    
576
static portBASE_TYPE field_meter_enabled = 0;
577
#define FIELD_METER_WIDTH 80
578
#define FIELD_METER_MAX_VALUE 160
579
#define FIELD_METER_SCALE_FACTOR (FIELD_METER_MAX_VALUE/FIELD_METER_WIDTH)
580
// 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
					(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
			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
portBASE_TYPE vCmdInit() {
615
	unsigned int i;
616
	for(i=0; i<sizeof(PIO_PINS)/sizeof(PIO_PINS[0]); i++) {
617
		if(PIO_PINS[i].dynpin == DYNAMIC_PIN_PLL_LOCK) {
618
			PIO_PINS[i].pin = OPENPICC->PLL_LOCK;
619
			PIO_PINS[i].dynpin = 0;
620
		}
621
	}
622
	
623
	/* FIXME Maybe modify to use pointers? */
624
	xCmdQueue = xQueueCreate( 10, sizeof(cmd_type) );
625
	if(xCmdQueue == 0) {
626
		return 0;
627
	}
628
	vSemaphoreCreateBinary( xFieldMeterMutex );
629
	if(xFieldMeterMutex == 0) {
630
		return 0;
631
	}
632
	xSemaphoreTake(xFieldMeterMutex, portMAX_DELAY);
633
	
634
	if(xTaskCreate(vCmdCode, (signed portCHAR *)"CMD", TASK_CMD_STACK, NULL, 
635
		TASK_CMD_PRIORITY, &xCmdTask) != pdPASS) {
636
		return 0;
637
	}
638
	
639
	if(xTaskCreate(vCmdRecvUsbCode, (signed portCHAR *)"CMDUSB", 128, NULL, 
640
		TASK_CMD_PRIORITY, &xCmdRecvUsbTask) != pdPASS) {
641
		return 0;
642
	}
643
	
644
	if(xTaskCreate(vFieldMeter, (signed portCHAR *)"FIELD METER", 128, NULL, 
645
		TASK_CMD_PRIORITY, &xFieldMeterTask) != pdPASS) {
646
		return 0;
647
	}
648
	
649
	return 1;
650
}
(5-5/59)
Add picture from clipboard (Maximum size: 48.8 MB)