Project

General

Profile

Download (12.3 KB) Statistics
| Branch: | Tag: | Revision:
1 a4d26bb5 Harald Welte
/* ----------------------------------------------------------------------------
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 c4166bf8 Harald Welte
#include <errno.h>
31
#include <string.h>
32
#include <stdlib.h>
33
34 a4d26bb5 Harald Welte
#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 a95b61f3 Sylvain Munaut
#include <usb/device/dfu/dfu.h>
47 a4d26bb5 Harald Welte
48
#include <dmad/dmad.h>
49
#include <dma/dma.h>
50
51
#include <tuner_e4k.h>
52
#include <si570.h>
53 5fb405d4 Harald Welte
#include <osdr_fpga.h>
54 e81bf0ed Harald Welte
#include <req_ctx.h>
55 c4166bf8 Harald Welte
#include <uart_cmd.h>
56 02974149 Harald Welte
#include <fast_source.h>
57 a4d26bb5 Harald Welte
58
#define SSC_MCK    49152000
59
60
// TWI clock
61 323af344 Christian Daniel
#define TWI_CLOCK       400000
62 a4d26bb5 Harald Welte
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 e81bf0ed Harald Welte
/// 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 a4d26bb5 Harald Welte
86
/// List of pins to configure.
87 5fb405d4 Harald Welte
static const Pin pins[] = {PINS_TWI0, PIN_PCK0, PINS_LEDS, PINS_SPI0,
88 a4d26bb5 Harald Welte
			   PINS_MISC, PINS_SSC, PINS_FPGA_JTAG};
89
90
static Twid twid;
91 65f6e41c Christian Daniel
struct e4k_state e4k;
92
struct si570_ctx si570;
93 a4d26bb5 Harald Welte
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 e81bf0ed Harald Welte
/*----------------------------------------------------------------------------
114
 *         VBus monitoring (optional)
115
 *----------------------------------------------------------------------------*/
116 45f0e31e Harald Welte
117 e81bf0ed Harald Welte
/**  VBus pin instance. */
118
static const Pin pinVbus = PIN_USB_VBUS;
119 45f0e31e Harald Welte
120 e81bf0ed Harald Welte
/**
121
 *  Handles interrupts coming from PIO controllers.
122
 */
123
static void ISR_Vbus(const Pin *pPin)
124 45f0e31e Harald Welte
{
125 e81bf0ed Harald Welte
    /* 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 45f0e31e Harald Welte
}
137
138 e81bf0ed Harald Welte
/**
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 45f0e31e Harald Welte
{
144 e81bf0ed Harald Welte
    /* 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 45f0e31e Harald Welte
}
161
162
163 e81bf0ed Harald Welte
/*----------------------------------------------------------------------------
164
 *         Callbacks re-implementation
165
 *----------------------------------------------------------------------------*/
166 45f0e31e Harald Welte
167 e81bf0ed Harald Welte
//------------------------------------------------------------------------------
168
/// Invoked when the USB device leaves the Suspended state. By default,
169
/// configures the LEDs.
170
//------------------------------------------------------------------------------
171
void USBDCallbacks_Resumed(void)
172 45f0e31e Harald Welte
{
173 e81bf0ed Harald Welte
    USBState = STATE_RESUME;
174 45f0e31e Harald Welte
}
175
176 e81bf0ed Harald Welte
//------------------------------------------------------------------------------
177
/// Invoked when the USB device gets suspended. By default, turns off all LEDs.
178
//------------------------------------------------------------------------------
179
void USBDCallbacks_Suspended(void)
180 45f0e31e Harald Welte
{
181 e81bf0ed Harald Welte
    USBState = STATE_SUSPEND;
182 45f0e31e Harald Welte
}
183 e81bf0ed Harald Welte
184 02974149 Harald Welte
185 c4166bf8 Harald Welte
static struct cmd_state cmd_state;
186
187
static int cmd_tuner_init(struct cmd_state *cs, enum cmd_op op,
188 5a389db1 Harald Welte
			  const char *cmd, int argc, char **argv)
189 e81bf0ed Harald Welte
{
190 c4166bf8 Harald Welte
	e4k_init(&e4k);
191
	return 0;
192
}
193
194 8930b8a3 Harald Welte
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 c4166bf8 Harald Welte
static int cmd_rf_freq(struct cmd_state *cs, enum cmd_op op,
206 5a389db1 Harald Welte
		       const char *cmd, int argc, char **argv)
207 c4166bf8 Harald Welte
{
208
	uint32_t freq;
209
210
	switch (op) {
211
	case CMD_OP_SET:
212 5a389db1 Harald Welte
		if (argc < 1)
213
			return -EINVAL;
214
		freq = strtoul(argv[0], NULL, 10);
215 c4166bf8 Harald Welte
		e4k_tune_freq(&e4k, freq);
216 e81bf0ed Harald Welte
		break;
217 c4166bf8 Harald Welte
	case CMD_OP_GET:
218
		freq = e4k.vco.flo;
219
		uart_cmd_out(cs, "%s:%u\n\r", cmd, freq);
220 e81bf0ed Harald Welte
		break;
221 c4166bf8 Harald Welte
	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 5a389db1 Harald Welte
			  const char *cmd, int argc, char **argv)
230 c4166bf8 Harald Welte
{
231
	uint32_t freq;
232
233
	switch (op) {
234
	case CMD_OP_SET:
235 5a389db1 Harald Welte
		if (argc < 1)
236
			return -EINVAL;
237
		freq = strtoul(argv[0], NULL, 10);
238 c4166bf8 Harald Welte
		set_si570_freq(freq);
239 e81bf0ed Harald Welte
		break;
240 c4166bf8 Harald Welte
	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 5a389db1 Harald Welte
			  const char *cmd, int argc, char **argv)
248 c4166bf8 Harald Welte
{
249
	si570_regdump(&si570);
250
	return 0;
251
}
252
253 67877f16 Harald Welte
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 bd2b9a96 Harald Welte
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 463a3f9c Christian Daniel
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 4683c1c2 Christian Daniel
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 b93708ed Christian Daniel
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 a95b61f3 Sylvain Munaut
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 c4166bf8 Harald Welte
static struct cmd cmds[] = {
352 8930b8a3 Harald Welte
	{ "tuner.init", CMD_OP_EXEC, cmd_tuner_init,
353 c4166bf8 Harald Welte
	  "Initialize the tuner" },
354 b93708ed Christian Daniel
	{ "tuner.dump", CMD_OP_EXEC, cmd_tuner_dump,
355
	  "Dump E4k registers" },
356 c4166bf8 Harald Welte
	{ "tuner.freq", CMD_OP_SET|CMD_OP_GET, cmd_rf_freq,
357
	  "Tune to the specified frequency" },
358 f49513d4 Harald Welte
	{ "tuner.gain", CMD_OP_SET, cmd_tuner_gain,
359 8930b8a3 Harald Welte
	  "Tune to the specified gain" },
360 67877f16 Harald Welte
	{ "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 bd2b9a96 Harald Welte
	{ "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 463a3f9c Christian Daniel
	{ "tuner.commonmode", CMD_OP_SET, cmd_tuner_commonmode,
371
	  "Switch common mode voltage" },
372 4683c1c2 Christian Daniel
	{ "tuner.iqofs", CMD_OP_SET, cmd_tuner_iqofs,
373
	  "Manually set I/Q offset and correction range" },
374 2a2c03a7 Harald Welte
375 c4166bf8 Harald Welte
	{ "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 2a2c03a7 Harald Welte
380 a95b61f3 Sylvain Munaut
	{ "dfu", CMD_OP_EXEC, cmd_dfu,
381
	  "Enter DFU mode" },
382 c4166bf8 Harald Welte
};
383
384 a4d26bb5 Harald Welte
//------------------------------------------------------------------------------
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 dc23dc5a Harald Welte
    printf("-- OsmoSDR firmware (" BOARD_NAME ") " GIT_REVISION " --\n\r");
428 a4d26bb5 Harald Welte
    printf("-- Compiled: %s %s --\n\r", __DATE__, __TIME__);
429
430 c4166bf8 Harald Welte
	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 e81bf0ed Harald Welte
437
	fastsource_init();
438
	VBus_Configure();
439
440 45f0e31e Harald Welte
	power_peripherals(1);
441 c4166bf8 Harald Welte
442 45f0e31e Harald Welte
	si570_init(&si570, &twid, SI570_I2C_ADDR);
443
	set_si570_freq(30000000);
444 c4166bf8 Harald Welte
445
	sam3u_e4k_init(&e4k, &twid, E4K_I2C_ADDR);
446 65f6e41c Christian Daniel
	e4k.vco.fosc = 30000000;
447 c4166bf8 Harald Welte
448 45f0e31e Harald Welte
	osdr_fpga_init(SSC_MCK);
449 a5d9d2de Christian Daniel
	//osdr_fpga_reg_write(OSDR_FPGA_REG_ADC_TIMING, (1 << 8) | 255);
450 65f6e41c Christian Daniel
	//osdr_fpga_reg_write(OSDR_FPGA_REG_PWM1, (1 << 400) | 800);
451 a5d9d2de Christian Daniel
	osdr_fpga_set_iq_swap(0);
452 45f0e31e Harald Welte
453 02974149 Harald Welte
	ssc_init();
454 d62195b0 Christian Daniel
	e4k_init(&e4k);
455
	e4k_init(&e4k);
456 02974149 Harald Welte
457 a4d26bb5 Harald Welte
    // Enter menu loop
458
    while (1) {
459
460 65f6e41c Christian Daniel
    	if (DBGU_IsRxReady()) {
461 e81bf0ed Harald Welte
        	key = DBGU_GetChar();
462
        	// Process user input
463 65f6e41c Christian Daniel
        	if (uart_cmd_char(&cmd_state, key) == 1) {
464
        		//ssc_stats();
465
        	}
466
    	}
467
    	ssc_dma_start();
468
    	fastsource_start();
469 a4d26bb5 Harald Welte
    }
470
}
Add picture from clipboard (Maximum size: 48.8 MB)