Project

General

Profile

Download (12.3 KB) Statistics
| Branch: | Tag: | Revision:
1
/* ----------------------------------------------------------------------------
2
 *         ATMEL Microcontroller Software Support 
3
 * ----------------------------------------------------------------------------
4
 * Copyright (c) 2008, Atmel Corporation
5
 *
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions are met:
10
 *
11
 * - Redistributions of source code must retain the above copyright notice,
12
 * this list of conditions and the disclaimer below.
13
 *
14
 * Atmel's name may not be used to endorse or promote products derived from
15
 * this software without specific prior written permission.
16
 *
17
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20
 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 * ----------------------------------------------------------------------------
28
 */
29

    
30
#include <errno.h>
31
#include <string.h>
32
#include <stdlib.h>
33

    
34
#include <board.h>
35
#include <board_memories.h>
36
#include <pio/pio.h>
37
#include <irq/irq.h>
38
#include <twi/twid.h>
39
#include <twi/twi.h>
40
#include <dbgu/dbgu.h>
41
#include <ssc/ssc.h>
42
#include <utility/assert.h>
43
#include <utility/math.h>
44
#include <utility/trace.h>
45
#include <utility/led.h>
46
#include <usb/device/dfu/dfu.h>
47

    
48
#include <dmad/dmad.h>
49
#include <dma/dma.h>
50

    
51
#include <tuner_e4k.h>
52
#include <si570.h>
53
#include <osdr_fpga.h>
54
#include <req_ctx.h>
55
#include <uart_cmd.h>
56
#include <fast_source.h>
57

    
58
#define SSC_MCK    49152000
59

    
60
// TWI clock
61
#define TWI_CLOCK       400000
62

    
63
// PMC define
64
#define AT91C_CKGR_PLLR     AT91C_CKGR_PLLAR
65
#define AT91C_PMC_LOCK      AT91C_PMC_LOCKA
66

    
67
#define AT91C_CKGR_MUL_SHIFT         16
68
#define AT91C_CKGR_OUT_SHIFT         14
69
#define AT91C_CKGR_PLLCOUNT_SHIFT     8
70
#define AT91C_CKGR_DIV_SHIFT          0
71

    
72
#define E4K_I2C_ADDR 		0x64
73
#define SI570_I2C_ADDR 		0x55
74

    
75
//------------------------------------------------------------------------------
76
//         Local variables
77
//------------------------------------------------------------------------------
78
/// Use for power management
79
#define STATE_IDLE    0
80
/// The USB device is in suspend state
81
#define STATE_SUSPEND 4
82
/// The USB device is in resume state
83
#define STATE_RESUME  5
84
unsigned char USBState = STATE_IDLE;
85

    
86
/// List of pins to configure.
87
static const Pin pins[] = {PINS_TWI0, PIN_PCK0, PINS_LEDS, PINS_SPI0,
88
			   PINS_MISC, PINS_SSC, PINS_FPGA_JTAG};
89

    
90
static Twid twid;
91
struct e4k_state e4k;
92
struct si570_ctx si570;
93

    
94
static void set_si570_freq(uint32_t freq)
95
{
96
	si570_set_freq(&si570, freq/1000, 0);
97
	e4k.vco.fosc = freq;
98
}
99

    
100
static void power_peripherals(int on)
101
{
102
	if (on) {
103
		osdr_fpga_power(1);
104
		sam3u_e4k_power(&e4k, 1);
105
		sam3u_e4k_stby(&e4k, 0);
106
	} else {
107
		osdr_fpga_power(0);
108
		sam3u_e4k_stby(&e4k, 1);
109
		sam3u_e4k_power(&e4k, 0);
110
	}
111
}
112

    
113
/*----------------------------------------------------------------------------
114
 *         VBus monitoring (optional)
115
 *----------------------------------------------------------------------------*/
116

    
117
/**  VBus pin instance. */
118
static const Pin pinVbus = PIN_USB_VBUS;
119

    
120
/**
121
 *  Handles interrupts coming from PIO controllers.
122
 */
123
static void ISR_Vbus(const Pin *pPin)
124
{
125
    /* Check current level on VBus */
126
    if (PIO_Get(&pinVbus))
127
    {
128
        TRACE_INFO("VBUS conn\n\r");
129
        USBD_Connect();
130
    }
131
    else
132
    {
133
        TRACE_INFO("VBUS discon\n\r");
134
        USBD_Disconnect();
135
    }
136
}
137

    
138
/**
139
 *  Configures the VBus pin to trigger an interrupt when the level on that pin
140
 *  changes.
141
 */
142
static void VBus_Configure( void )
143
{
144
    /* Configure PIO */
145
    PIO_Configure(&pinVbus, 1);
146
    PIO_ConfigureIt(&pinVbus, ISR_Vbus);
147
    PIO_EnableIt(&pinVbus);
148

    
149
    /* Check current level on VBus */
150
    if (PIO_Get(&pinVbus))
151
    {
152
        /* if VBUS present, force the connect */
153
        USBD_Connect();
154
    }
155
    else
156
    {
157
        TRACE_INFO("discon\n\r");
158
        USBD_Disconnect();
159
    }
160
}
161

    
162

    
163
/*----------------------------------------------------------------------------
164
 *         Callbacks re-implementation
165
 *----------------------------------------------------------------------------*/
166

    
167
//------------------------------------------------------------------------------
168
/// Invoked when the USB device leaves the Suspended state. By default,
169
/// configures the LEDs.
170
//------------------------------------------------------------------------------
171
void USBDCallbacks_Resumed(void)
172
{
173
    USBState = STATE_RESUME;
174
}
175

    
176
//------------------------------------------------------------------------------
177
/// Invoked when the USB device gets suspended. By default, turns off all LEDs.
178
//------------------------------------------------------------------------------
179
void USBDCallbacks_Suspended(void)
180
{
181
    USBState = STATE_SUSPEND;
182
}
183

    
184

    
185
static struct cmd_state cmd_state;
186

    
187
static int cmd_tuner_init(struct cmd_state *cs, enum cmd_op op,
188
			  const char *cmd, int argc, char **argv)
189
{
190
	e4k_init(&e4k);
191
	return 0;
192
}
193

    
194
static int cmd_tuner_gain(struct cmd_state *cs, enum cmd_op op,
195
			  const char *cmd, int argc, char **argv)
196
{
197
	int i;
198

    
199
	for (i = 0; i < argc; i++)
200
		e4k_if_gain_set(&e4k, i+1, atoi(argv[i]));
201

    
202
	return 0;
203
}
204

    
205
static int cmd_rf_freq(struct cmd_state *cs, enum cmd_op op,
206
		       const char *cmd, int argc, char **argv)
207
{
208
	uint32_t freq;
209

    
210
	switch (op) {
211
	case CMD_OP_SET:
212
		if (argc < 1)
213
			return -EINVAL;
214
		freq = strtoul(argv[0], NULL, 10);
215
		e4k_tune_freq(&e4k, freq);
216
		break;
217
	case CMD_OP_GET:
218
		freq = e4k.vco.flo;
219
		uart_cmd_out(cs, "%s:%u\n\r", cmd, freq);
220
		break;
221
	default:
222
		return -EINVAL;
223
	}
224

    
225
	return 0;
226
}
227

    
228
static int cmd_si570_freq(struct cmd_state *cs, enum cmd_op op,
229
			  const char *cmd, int argc, char **argv)
230
{
231
	uint32_t freq;
232

    
233
	switch (op) {
234
	case CMD_OP_SET:
235
		if (argc < 1)
236
			return -EINVAL;
237
		freq = strtoul(argv[0], NULL, 10);
238
		set_si570_freq(freq);
239
		break;
240
	default:
241
		return -EINVAL;
242
	}
243
	return 0;
244
}
245

    
246
static int cmd_si570_dump(struct cmd_state *cs, enum cmd_op op,
247
			  const char *cmd, int argc, char **argv)
248
{
249
	si570_regdump(&si570);
250
	return 0;
251
}
252

    
253
static int cmd_flt_bw(struct cmd_state *cs, enum cmd_op op,
254
		      const char *cmd, int argc, char **argv)
255
{
256
	enum e4k_if_filter filt;
257
	int bw, rc;
258

    
259
	if (!strcmp(cmd, "tuner.flt_bw_mix"))
260
		filt = E4K_IF_FILTER_MIX;
261
	else if (!strcmp(cmd, "tuner.flt_bw_chan"))
262
		filt = E4K_IF_FILTER_CHAN;
263
	else if (!strcmp(cmd, "tuner.flt_bw_rc"))
264
		filt = E4K_IF_FILTER_RC;
265
	else
266
		return -EINVAL;
267

    
268
	switch (op) {
269
	case CMD_OP_GET:
270
		bw = e4k_if_filter_bw_get(&e4k, filt);
271
		uart_cmd_out(cs, "%s:%d\n\r", cmd, bw);
272
		break;
273
	case CMD_OP_SET:
274
		if (argc < 1)
275
			return -EINVAL;
276
		rc = e4k_if_filter_bw_set(&e4k, filt, atoi(argv[0]));
277
		if (rc < 0)
278
			return -EINVAL;
279
		break;
280
	default:
281
		return -EINVAL;
282
	}
283

    
284
	return 0;
285
}
286

    
287
static int cmd_tuner_dco(struct cmd_state *cs, enum cmd_op op,
288
			 const char *cmd, int argc, char **argv)
289
{
290
	return e4k_dc_offset_calibrate(&e4k);
291
}
292

    
293
static int cmd_tuner_dco_table(struct cmd_state *cs, enum cmd_op op,
294
			 const char *cmd, int argc, char **argv)
295
{
296
	return e4k_dc_offset_gen_table(&e4k);
297
}
298

    
299
static int cmd_tuner_commonmode(struct cmd_state *cs, enum cmd_op op,
300
			const char *cmd, int argc, char **argv)
301
{
302
	int32_t cm;
303

    
304
	switch (op) {
305
	case CMD_OP_SET:
306
		if (argc < 1)
307
			return -EINVAL;
308
		cm = strtoul(argv[0], NULL, 10);
309
		e4k_commonmode_set(&e4k, cm);
310
		break;
311
	default:
312
		return -EINVAL;
313
	}
314
	return 0;
315
}
316

    
317
static int cmd_tuner_iqofs(struct cmd_state *cs, enum cmd_op op,
318
			const char *cmd, int argc, char ** argv)
319
{
320
	int iofs;
321
	int qofs;
322
	int irange;
323
	int qrange;
324

    
325
	if(op != CMD_OP_SET)
326
		return -EINVAL;
327
	if(argc < 4)
328
		return -EINVAL;
329

    
330
	iofs = strtol(argv[0], NULL, 10);
331
	qofs = strtol(argv[1], NULL, 10);
332
	irange = strtol(argv[2], NULL, 10);
333
	qrange = strtol(argv[3], NULL, 10);
334

    
335
	return e4k_manual_dc_offset(&e4k, iofs, irange, qofs, qrange);
336
}
337

    
338
static int cmd_tuner_dump(struct cmd_state *cs, enum cmd_op op,
339
	const char *cmd, int argc, char ** argv)
340
{
341
	return e4k_dump(&e4k);
342
}
343

    
344
static int cmd_dfu(struct cmd_state *cs, enum cmd_op op,
345
                   const char *cmd, int argc, char ** argv)
346
{
347
	*((volatile unsigned long *)USB_DFU_MAGIC_ADDR) = USB_DFU_MAGIC;
348
	NVIC_SystemReset();
349
}
350

    
351
static struct cmd cmds[] = {
352
	{ "tuner.init", CMD_OP_EXEC, cmd_tuner_init,
353
	  "Initialize the tuner" },
354
	{ "tuner.dump", CMD_OP_EXEC, cmd_tuner_dump,
355
	  "Dump E4k registers" },
356
	{ "tuner.freq", CMD_OP_SET|CMD_OP_GET, cmd_rf_freq,
357
	  "Tune to the specified frequency" },
358
	{ "tuner.gain", CMD_OP_SET, cmd_tuner_gain,
359
	  "Tune to the specified gain" },
360
	{ "tuner.flt_bw_mix", CMD_OP_SET|CMD_OP_GET, cmd_flt_bw,
361
	  "Filter bandwidth (Mixer)" },
362
	{ "tuner.flt_bw_chan", CMD_OP_SET|CMD_OP_GET, cmd_flt_bw,
363
	  "Filter bandwidth (Channel)" },
364
	{ "tuner.flt_bw_rc", CMD_OP_SET|CMD_OP_GET, cmd_flt_bw,
365
	  "Filter bandwidth (RC)" },
366
	{ "tuner.dc_calib", CMD_OP_EXEC, cmd_tuner_dco,
367
	  "Perform DC offset calibration" },
368
	{ "tuner.dc_table", CMD_OP_EXEC, cmd_tuner_dco_table,
369
	  "Generate DC offset table" },
370
	{ "tuner.commonmode", CMD_OP_SET, cmd_tuner_commonmode,
371
	  "Switch common mode voltage" },
372
	{ "tuner.iqofs", CMD_OP_SET, cmd_tuner_iqofs,
373
	  "Manually set I/Q offset and correction range" },
374

    
375
	{ "si570.freq", CMD_OP_SET|CMD_OP_GET, cmd_si570_freq,
376
	  "Change the SI570 clock frequency" },
377
	{ "si570.dump", CMD_OP_EXEC, cmd_si570_dump,
378
	  "Dump SI570 registers" },
379

    
380
	{ "dfu", CMD_OP_EXEC, cmd_dfu,
381
	  "Enter DFU mode" },
382
};
383

    
384
//------------------------------------------------------------------------------
385
/// Main function
386
//------------------------------------------------------------------------------
387
int main(void)
388
{
389
    unsigned char key;
390
    unsigned char isValid;
391

    
392
    // Configure all pins
393
    PIO_Configure(pins, PIO_LISTSIZE(pins));
394

    
395
    LED_Configure(0);
396
    LED_Set(0);
397
    LED_Configure(1);
398
    LED_Set(1);
399

    
400
    // Initialize the DBGU
401
    TRACE_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK);
402

    
403
    // Switch to Main clock
404
    AT91C_BASE_PMC->PMC_MCKR = (AT91C_BASE_PMC->PMC_MCKR & ~AT91C_PMC_CSS) | AT91C_PMC_CSS_MAIN_CLK;
405
    while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) == 0);
406

    
407
    // Configure PLL to 98.285MHz
408
    *AT91C_CKGR_PLLR = ((1 << 29) | (171 << AT91C_CKGR_MUL_SHIFT) \
409
        | (0x0 << AT91C_CKGR_OUT_SHIFT) |(0x3f << AT91C_CKGR_PLLCOUNT_SHIFT) \
410
        | (21 << AT91C_CKGR_DIV_SHIFT));
411
    while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK) == 0);
412

    
413
    // Configure master clock in two operations
414
    AT91C_BASE_PMC->PMC_MCKR = (( AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_PLLA_CLK) & ~AT91C_PMC_CSS) | AT91C_PMC_CSS_MAIN_CLK;
415
    while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) == 0);
416
    AT91C_BASE_PMC->PMC_MCKR = ( AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_PLLA_CLK);
417
    while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) == 0);
418

    
419
    // DBGU reconfiguration
420
    DBGU_Configure(DBGU_STANDARD, 115200, SSC_MCK);
421

    
422
    // Configure and enable the TWI (required for accessing the DAC)
423
    *AT91C_PMC_PCER = (1<< AT91C_ID_TWI0); 
424
    TWI_ConfigureMaster(AT91C_BASE_TWI0, TWI_CLOCK, SSC_MCK);
425
    TWID_Initialize(&twid, AT91C_BASE_TWI0);
426

    
427
    printf("-- OsmoSDR firmware (" BOARD_NAME ") " GIT_REVISION " --\n\r");
428
    printf("-- Compiled: %s %s --\n\r", __DATE__, __TIME__);
429

    
430
	req_ctx_init();
431
	PIO_InitializeInterrupts(0);
432

    
433
	cmd_state.out = vprintf;
434
	uart_cmd_reset(&cmd_state);
435
	uart_cmds_register(cmds, sizeof(cmds)/sizeof(cmds[0]));
436

    
437
	fastsource_init();
438
	VBus_Configure();
439

    
440
	power_peripherals(1);
441

    
442
	si570_init(&si570, &twid, SI570_I2C_ADDR);
443
	set_si570_freq(30000000);
444

    
445
	sam3u_e4k_init(&e4k, &twid, E4K_I2C_ADDR);
446
	e4k.vco.fosc = 30000000;
447

    
448
	osdr_fpga_init(SSC_MCK);
449
	//osdr_fpga_reg_write(OSDR_FPGA_REG_ADC_TIMING, (1 << 8) | 255);
450
	//osdr_fpga_reg_write(OSDR_FPGA_REG_PWM1, (1 << 400) | 800);
451
	osdr_fpga_set_iq_swap(0);
452

    
453
	ssc_init();
454
	e4k_init(&e4k);
455
	e4k_init(&e4k);
456

    
457
    // Enter menu loop
458
    while (1) {
459

    
460
    	if (DBGU_IsRxReady()) {
461
        	key = DBGU_GetChar();
462
        	// Process user input
463
        	if (uart_cmd_char(&cmd_state, key) == 1) {
464
        		//ssc_stats();
465
        	}
466
    	}
467
    	ssc_dma_start();
468
    	fastsource_start();
469
    }
470
}
(2-2/2)
Add picture from clipboard (Maximum size: 48.8 MB)