Remove \version svn tag.
[bertos.git] / boards / at91sam7s-ek / hw / hw_afsk.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2006 Develer S.r.l. (http://www.develer.com/)
30  * All Rights Reserved.
31  * -->
32  *
33  * \brief AFSK modem hardware-specific definitions.
34  *
35  *
36  * \author Francesco Sacchi <batt@develer.com>
37  */
38
39
40 #include <net/afsk.h>
41 #include <drv/pwm.h>
42
43 #include <io/arm.h>
44 #include <cfg/compiler.h>
45 #include <cfg/macros.h>
46 #include <cfg/module.h>
47
48
49 #define CONFIG_ADC_CLOCK        4800000UL
50 #define CONFIG_ADC_STARTUP_TIME 20
51 #define CONFIG_ADC_SHTIME       834
52
53 #define ADC_COMPUTED_PRESCALER    ((CPU_FREQ/(2 * CONFIG_ADC_CLOCK)) - 1)
54 #define ADC_COMPUTED_STARTUPTIME  (((CONFIG_ADC_STARTUP_TIME * CONFIG_ADC_CLOCK)/ 8000000UL) - 1)
55 #define ADC_COMPUTED_SHTIME       (((CONFIG_ADC_SHTIME * CONFIG_ADC_CLOCK)/1000000000UL) - 1)
56
57 static Afsk *afsk_ctx;
58 bool hw_afsk_dac_isr;
59
60
61 static void __attribute__((interrupt)) hw_afsk_adc_isr(void)
62 {
63         afsk_adc_isr(afsk_ctx, ADC_LCDR - 128);
64
65         /* Enable block writing */
66         PIOA_OWER = DAC_PIN_MASK;
67
68         if (hw_afsk_dac_isr)
69                 PIOA_ODSR = (afsk_dac_isr(afsk_ctx) << 15) & DAC_PIN_MASK;
70         else
71                 /* Vdac/2 = 128 */
72                 PIOA_ODSR = 0x4000000;
73
74         PIOA_OWDR = DAC_PIN_MASK;
75
76         AIC_EOICR = 0;
77 }
78
79 void hw_afsk_adc_init(int ch, struct Afsk * ctx)
80 {
81         afsk_ctx = ctx;
82         afsk_ctx->adc_ch = ch;
83         ADC_MR = 0;
84         ADC_MR |= BV(ADC_LOWRES);
85
86         //Apply computed prescaler value
87         ADC_MR &= ~ADC_PRESCALER_MASK;
88         ADC_MR |= ((ADC_COMPUTED_PRESCALER << ADC_PRESCALER_SHIFT) & ADC_PRESCALER_MASK);
89
90         //Apply computed start up time
91         ADC_MR &= ~ADC_STARTUP_MASK;
92         ADC_MR |= ((ADC_COMPUTED_STARTUPTIME << ADC_STARTUP_SHIFT) & ADC_STARTUP_MASK);
93
94         //Apply computed sample and hold time
95         ADC_MR &= ~ADC_SHTIME_MASK;
96         ADC_MR |= ((ADC_COMPUTED_SHTIME << ADC_SHTIME_SHIFT) & ADC_SHTIME_MASK);
97
98         // Disable all interrupt
99         ADC_IDR = 0xFFFFFFFF;
100
101         //Register interrupt vector
102         AIC_SVR(ADC_ID) = hw_afsk_adc_isr;
103         AIC_SMR(ADC_ID) = AIC_SRCTYPE_INT_EDGE_TRIGGERED;
104         AIC_IECR = BV(ADC_ID);
105
106         //Enable data ready irq
107         ADC_IER = BV(ADC_DRDY);
108
109         ///////
110         PMC_PCER = BV(TC0_ID);
111         TC_BMR = TC_NONEXC0;
112         TC0_CCR = BV(TC_SWTRG) | BV(TC_CLKEN);
113
114         TC0_CMR = BV(TC_WAVE);
115         TC0_CMR |= (TC_WAVSEL_UP_RC_TRG | TC_ACPC_CLEAR_OUTPUT | TC_ACPA_SET_OUTPUT);
116         TC0_RC = (CPU_FREQ / 2) / 9600;
117         TC0_RA = TC0_RC / 2;
118         ///////
119
120         // Auto trigger enabled on TIOA channel 0
121         ADC_MR |= BV(ADC_TRGEN);
122
123         //Disable all channels
124         ADC_CHDR = ADC_CH_MASK;
125         //Enable channel
126         ADC_CHER = BV(ch);
127 }