Add DMA example
[fw/altos] / target / dma / dma.c
1 /*
2  * Copyright © 2008 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 #include <stdint.h>
20
21 /*
22  * Test DMA
23  */
24
25 sfr at 0x80 P0;
26 sfr at 0x90 P1;
27 sfr at 0xA0 P2;
28 sfr at 0xC6 CLKCON;
29 sfr at 0xbe SLEEP;
30
31 # define SLEEP_USB_EN           (1 << 7)
32 # define SLEEP_XOSC_STB         (1 << 6)
33
34 sfr at 0xF1 PERCFG;
35 #define PERCFG_T1CFG_ALT_1      (0 << 6)
36 #define PERCFG_T1CFG_ALT_2      (1 << 6)
37
38 #define PERCFG_T3CFG_ALT_1      (0 << 5)
39 #define PERCFG_T3CFG_ALT_2      (1 << 5)
40
41 #define PERCFG_T4CFG_ALT_1      (0 << 4)
42 #define PERCFG_T4CFG_ALT_2      (1 << 4)
43
44 #define PERCFG_U1CFG_ALT_1      (0 << 1)
45 #define PERCFG_U1CFG_ALT_2      (1 << 1)
46
47 #define PERCFG_U0CFG_ALT_1      (0 << 0)
48 #define PERCFG_U0CFG_ALT_2      (1 << 0)
49
50 sfr at 0xF2 ADCCFG;
51 sfr at 0xF3 P0SEL;
52 sfr at 0xF4 P1SEL;
53 sfr at 0xF5 P2SEL;
54
55 sfr at 0xFD P0DIR;
56 sfr at 0xFE P1DIR;
57 sfr at 0xFF P2DIR;
58 sfr at 0x8F P0INP;
59 sfr at 0xF6 P1INP;
60 sfr at 0xF7 P2INP;
61
62 sfr at 0x89 P0IFG;
63 sfr at 0x8A P1IFG;
64 sfr at 0x8B P2IFG;
65
66 sbit at 0x90 P1_0;
67 sbit at 0x91 P1_1;
68 sbit at 0x92 P1_2;
69 sbit at 0x93 P1_3;
70 sbit at 0x94 P1_4;
71 sbit at 0x95 P1_5;
72 sbit at 0x96 P1_6;
73 sbit at 0x97 P1_7;
74
75 /*
76  * UART registers
77  */
78
79 sfr at 0x86 U0CSR;
80 sfr at 0xF8 U1CSR;
81
82 /*
83  * IRCON2
84  */
85 sfr at 0xE8 IRCON2;     /* CPU Interrupt Flag 5 */
86
87 sbit at 0xE8 USBIF;     /* USB interrupt flag (shared with Port2) */
88 sbit at 0xE8 P2IF;      /* Port2 interrupt flag (shared with USB) */
89 sbit at 0xE9 UTX0IF;    /* USART0 TX interrupt flag */
90 sbit at 0xEA UTX1IF;    /* USART1 TX interrupt flag (shared with I2S TX) */
91 sbit at 0xEA I2STXIF;   /* I2S TX interrupt flag (shared with USART1 TX) */
92 sbit at 0xEB P1IF;      /* Port1 interrupt flag */
93 sbit at 0xEC WDTIF;     /* Watchdog timer interrupt flag */
94
95 # define UxCSR_MODE_UART                (1 << 7)
96 # define UxCSR_MODE_SPI                 (0 << 7)
97 # define UxCSR_RE                       (1 << 6)
98 # define UxCSR_SLAVE                    (1 << 5)
99 # define UxCSR_MASTER                   (0 << 5)
100 # define UxCSR_FE                       (1 << 4)
101 # define UxCSR_ERR                      (1 << 3)
102 # define UxCSR_RX_BYTE                  (1 << 2)
103 # define UxCSR_TX_BYTE                  (1 << 1)
104 # define UxCSR_ACTIVE                   (1 << 0)
105
106 sfr at 0xc4 U0UCR;
107 sfr at 0xfb U1UCR;
108
109 # define UxUCR_FLUSH                    (1 << 7)
110 # define UxUCR_FLOW_DISABLE             (0 << 6)
111 # define UxUCR_FLOW_ENABLE              (1 << 6)
112 # define UxUCR_D9_EVEN_PARITY           (0 << 5)
113 # define UxUCR_D9_ODD_PARITY            (1 << 5)
114 # define UxUCR_BIT9_8_BITS              (0 << 4)
115 # define UxUCR_BIT9_9_BITS              (1 << 4)
116 # define UxUCR_PARITY_DISABLE           (0 << 3)
117 # define UxUCR_PARITY_ENABLE            (1 << 3)
118 # define UxUCR_SPB_1_STOP_BIT           (0 << 2)
119 # define UxUCR_SPB_2_STOP_BITS          (1 << 2)
120 # define UxUCR_STOP_LOW                 (0 << 1)
121 # define UxUCR_STOP_HIGH                (1 << 1)
122 # define UxUCR_START_LOW                (0 << 0)
123 # define UxUCR_START_HIGH               (1 << 0)
124
125 sfr at 0xc5 U0GCR;
126 sfr at 0xfc U1GCR;
127
128 # define UxGCR_CPOL_NEGATIVE            (0 << 7)
129 # define UxGCR_CPOL_POSITIVE            (1 << 7)
130 # define UxGCR_CPHA_FIRST_EDGE          (0 << 6)
131 # define UxGCR_CPHA_SECOND_EDGE         (1 << 6)
132 # define UxGCR_ORDER_LSB                (0 << 5)
133 # define UxGCR_ORDER_MSB                (1 << 5)
134 # define UxGCR_BAUD_E_MASK              (0x1f)
135 # define UxGCR_BAUD_E_SHIFT             0
136
137 sfr at 0xc1 U0DBUF;
138 sfr at 0xf9 U1DBUF;
139 sfr at 0xc2 U0BAUD;
140 sfr at 0xfa U1BAUD;
141
142 #define DEBUG   P1_1
143
144
145 # define DMA_LEN_HIGH_VLEN_MASK         (7 << 5)
146 # define DMA_LEN_HIGH_VLEN_LEN          (0 << 5)
147 # define DMA_LEN_HIGH_VLEN_PLUS_1       (1 << 5)
148 # define DMA_LEN_HIGH_VLEN              (2 << 5)
149 # define DMA_LEN_HIGH_VLEN_PLUS_2       (3 << 5)
150 # define DMA_LEN_HIGH_VLEN_PLUS_3       (4 << 5)
151 # define DMA_LEN_HIGH_MASK              (0x1f)
152
153 # define DMA_CFG0_WORDSIZE_8            (0 << 7)
154 # define DMA_CFG0_WORDSIZE_16           (1 << 7)
155 # define DMA_CFG0_TMODE_MASK            (3 << 5)
156 # define DMA_CFG0_TMODE_SINGLE          (0 << 5)
157 # define DMA_CFG0_TMODE_BLOCK           (1 << 5)
158 # define DMA_CFG0_TMODE_REPEATED_SINGLE (2 << 5)
159 # define DMA_CFG0_TMODE_REPEATED_BLOCK  (3 << 5)
160
161 /*
162  * DMA triggers
163  */
164 # define DMA_CFG0_TRIGGER_NONE          0
165 # define DMA_CFG0_TRIGGER_PREV          1
166 # define DMA_CFG0_TRIGGER_T1_CH0        2
167 # define DMA_CFG0_TRIGGER_T1_CH1        3
168 # define DMA_CFG0_TRIGGER_T1_CH2        4
169 # define DMA_CFG0_TRIGGER_T2_OVFL       6
170 # define DMA_CFG0_TRIGGER_T3_CH0        7
171 # define DMA_CFG0_TRIGGER_T3_CH1        8
172 # define DMA_CFG0_TRIGGER_T4_CH0        9
173 # define DMA_CFG0_TRIGGER_T4_CH1        10
174 # define DMA_CFG0_TRIGGER_IOC_0         12
175 # define DMA_CFG0_TRIGGER_IOC_1         13
176 # define DMA_CFG0_TRIGGER_URX0          14
177 # define DMA_CFG0_TRIGGER_UTX0          15
178 # define DMA_CFG0_TRIGGER_URX1          16
179 # define DMA_CFG0_TRIGGER_UTX1          17
180 # define DMA_CFG0_TRIGGER_FLASH         18
181 # define DMA_CFG0_TRIGGER_RADIO         19
182 # define DMA_CFG0_TRIGGER_ADC_CHALL     20
183 # define DMA_CFG0_TRIGGER_ADC_CH0       21
184 # define DMA_CFG0_TRIGGER_ADC_CH1       22
185 # define DMA_CFG0_TRIGGER_ADC_CH2       23
186 # define DMA_CFG0_TRIGGER_ADC_CH3       24
187 # define DMA_CFG0_TRIGGER_ADC_CH4       25
188 # define DMA_CFG0_TRIGGER_ADC_CH5       26
189 # define DMA_CFG0_TRIGGER_ADC_CH6       27
190 # define DMA_CFG0_TRIGGER_I2SRX         27
191 # define DMA_CFG0_TRIGGER_ADC_CH7       28
192 # define DMA_CFG0_TRIGGER_I2STX         28
193 # define DMA_CFG0_TRIGGER_ENC_DW        29
194 # define DMA_CFG0_TRIGGER_DNC_UP        30
195
196 # define DMA_CFG1_SRCINC_MASK           (3 << 6)
197 # define DMA_CFG1_SRCINC_0              (0 << 6)
198 # define DMA_CFG1_SRCINC_1              (1 << 6)
199 # define DMA_CFG1_SRCINC_2              (2 << 6)
200 # define DMA_CFG1_SRCINC_MINUS_1        (3 << 6)
201
202 # define DMA_CFG1_DESTINC_MASK          (3 << 4)
203 # define DMA_CFG1_DESTINC_0             (0 << 4)
204 # define DMA_CFG1_DESTINC_1             (1 << 4)
205 # define DMA_CFG1_DESTINC_2             (2 << 4)
206 # define DMA_CFG1_DESTINC_MINUS_1       (3 << 4)
207
208 # define DMA_CFG1_IRQMASK               (1 << 3)
209 # define DMA_CFG1_M8                    (1 << 2)
210
211 # define DMA_CFG1_PRIORITY_MASK         (3 << 0)
212 # define DMA_CFG1_PRIORITY_LOW          (0 << 0)
213 # define DMA_CFG1_PRIORITY_NORMAL       (1 << 0)
214 # define DMA_CFG1_PRIORITY_HIGH         (2 << 0)
215
216 /*
217  * DMAARM - DMA Channel Arm
218  */
219
220 sfr at 0xD6 DMAARM;
221
222 # define DMAARM_ABORT                   (1 << 7)
223 # define DMAARM_DMAARM4                 (1 << 4)
224 # define DMAARM_DMAARM3                 (1 << 3)
225 # define DMAARM_DMAARM2                 (1 << 2)
226 # define DMAARM_DMAARM1                 (1 << 1)
227 # define DMAARM_DMAARM0                 (1 << 0)
228
229 /*
230  * DMAREQ - DMA Channel Start Request and Status
231  */
232
233 sfr at 0xD7 DMAREQ;
234
235 # define DMAREQ_DMAREQ4                 (1 << 4)
236 # define DMAREQ_DMAREQ3                 (1 << 3)
237 # define DMAREQ_DMAREQ2                 (1 << 2)
238 # define DMAREQ_DMAREQ1                 (1 << 1)
239 # define DMAREQ_DMAREQ0                 (1 << 0)
240
241 /*
242  * DMA configuration 0 address
243  */
244
245 sfr at 0xD5 DMA0CFGH;
246 sfr at 0xD4 DMA0CFGL;
247
248 /*
249  * DMA configuration 1-4 address
250  */
251
252 sfr at 0xD3 DMA1CFGH;
253 sfr at 0xD2 DMA1CFGL;
254
255 /*
256  * DMAIRQ - DMA Interrupt Flag
257  */
258
259 sfr at 0xD1 DMAIRQ;
260
261 # define DMAIRQ_DMAIF4                  (1 << 4)
262 # define DMAIRQ_DMAIF3                  (1 << 3)
263 # define DMAIRQ_DMAIF2                  (1 << 2)
264 # define DMAIRQ_DMAIF1                  (1 << 1)
265 # define DMAIRQ_DMAIF0                  (1 << 0)
266
267 struct cc_dma_channel {
268         uint8_t src_high;
269         uint8_t src_low;
270         uint8_t dst_high;
271         uint8_t dst_low;
272         uint8_t len_high;
273         uint8_t len_low;
274         uint8_t cfg0;
275         uint8_t cfg1;
276 };
277
278 #define nop()   _asm nop _endasm;
279
280 void
281 delay (unsigned char n)
282 {
283         unsigned char i = 0;
284         unsigned char j = 0;
285
286         n++;
287         while (--n != 0)
288                 while (--i != 0)
289                         while (--j != 0)
290                                 nop();
291 }
292
293 void
294 debug_byte(uint8_t byte)
295 {
296         uint8_t s;
297
298         for (s = 0; s < 8; s++) {
299                 DEBUG = byte & 1;
300                 delay(5);
301                 byte >>= 1;
302         }
303 }
304
305 struct cc_dma_channel __xdata config;
306
307 #define DMA_LEN 8
308
309 uint8_t __xdata dma_input[DMA_LEN];
310 uint8_t __xdata dma_output[DMA_LEN];
311
312 #define ADDRH(a)        (((uint16_t) (a)) >> 8)
313 #define ADDRL(a)        (((uint16_t) (a)))
314
315 void
316 dma_init(void)
317 {
318         int i;
319         config.cfg0 = (DMA_CFG0_WORDSIZE_8 |
320                        DMA_CFG0_TMODE_BLOCK |
321                        DMA_CFG0_TRIGGER_NONE);
322         config.cfg1 = (DMA_CFG1_SRCINC_1 |
323                        DMA_CFG1_DESTINC_1 |
324                        DMA_CFG1_PRIORITY_NORMAL);
325         
326         config.src_high = ADDRH(dma_input);
327         config.src_low = ADDRL(dma_input);
328         config.dst_high = ADDRH(dma_output);
329         config.dst_low = ADDRL(dma_output);
330         config.len_high = 0;
331         config.len_low = DMA_LEN;
332         DMA0CFGH = ADDRH(&config);
333         DMA0CFGL = ADDRL(&config);
334         for (i = 0; i < DMA_LEN; i++)
335                 dma_input[i] = i + 1;
336 }
337
338 void
339 dma_run(void)
340 {
341         DMAREQ |= 1;
342         DMAARM |= 1;
343         while (DMAARM & 1)
344                 ;
345 }
346
347 main ()
348 {
349         int i;
350         P1DIR |= 2;
351         CLKCON = 0;
352         while (!(SLEEP & SLEEP_XOSC_STB))
353                 ;
354         
355         dma_init();
356         dma_run();
357         for (;;) {
358                 for (i = 0; i < DMA_LEN; i++)
359                         debug_byte(dma_output[i]);
360         }
361 }