6855b450902818514d21246a606d6c596450a2ab
[firmerware] / src / driver / tic55x / grandstream-bt20x.c
1 /* Grandstream BT20x driver as an extension to the tic55x driver
2  *
3  * Ideally, all this would be is wiring to the generic functions of
4  * chips connected to the DSP.  And of course a lot of register setup
5  * code.  In practice, it is not as sharply divided, sometimes for
6  * reasons of efficiency, sometimes for other reasons.  The ideal is
7  * the best judgement however, and any debate on where code should go
8  * should be based on this ideal plus the realism that too much
9  * indirection will slow down a program that is going to deal with
10  * static hardware anyway.
11  *
12  * This file is part of 0cpm Firmerware.
13  *
14  * 0cpm Firmerware is Copyright (c)2011 Rick van Rein, OpenFortress.
15  *
16  * 0cpm Firmerware is free software: you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License as
18  * published by the Free Software Foundation, version 3.
19  *
20  * 0cpm Firmerware is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with 0cpm Firmerware.  If not, see <http://www.gnu.org/licenses/>.
27  */
28
29
30 #include <stdlib.h>
31 #include <stdarg.h>
32 #include <stdbool.h>
33 #include <stdint.h>
34
35 #define BOTTOM
36 #include <config.h>
37
38 #include <0cpm/cpu.h>
39 #include <0cpm/timer.h>
40 #include <0cpm/led.h>
41 #include <0cpm/kbd.h>
42 #include <0cpm/app.h>
43 #include <0cpm/show.h>
44 #include <0cpm/flash.h>
45 #include <0cpm/snd.h>
46 #include <0cpm/cons.h>
47
48 #include <bottom/ht162x.h>
49 #include <bottom/ksz8842.h>
50
51
52
53 /******** EXTERNAL INTERRUPTS SERVICE ROUTINES ********/
54
55
56 interrupt void tic55x_int0_isr (void) {
57         tic55x_top_has_been_interrupted = true;
58         ksz8842_interrupt_handler ();
59 }
60
61 #if 0
62 interrupt void tic55x_int1 (void) {
63         tic55x_top_has_been_interrupted = true;
64         //TODO//
65 }
66
67 interrupt void tic55x_int2 (void) {
68         tic55x_top_has_been_interrupted = true;
69         //TODO//
70 }
71
72 interrupt void tic55x_int3 (void) {
73         tic55x_top_has_been_interrupted = true;
74         //TODO//
75 }
76 #endif
77
78
79
80 /******** FLASH PARTITION ACCESS ********/
81
82
83 /* An external definition (usually in phone-specific code)
84  * contains an array of at least one entry of flashpart
85  * structures.  Only the last will have the FLASHPART_FLAG_LAST
86  * flag set.
87  *
88  * There will usually be one partition with name ALLFLASH.BIN
89  * that covers the entire flash memory, including things that
90  * may not actually be in any partition.  Usually, this is the
91  * last entry in the flash partition table.
92  */
93 struct flashpart bottom_flash_partition_table [] = {
94         { FLASHPART_FLAG_LAST, "ALLFLASH.BIN", 0, 4096 }
95 };
96
97
98 /* Read a 512-byte block from flash.
99  * The return value indicates success.
100  */
101 bool bottom_flash_read (uint16_t blocknr, uint8_t data [512]) {
102         uint32_t flashidx;
103         uint16_t ctr = 0;
104         if (blocknr >= 4096) {
105                 return false;
106         }
107         flashidx = ((uint32_t) blocknr) * 256;
108         while (ctr < 512) {
109                 uint16_t sample = flash_16 [flashidx];
110                 flashidx += 1;
111                 // data [ctr++] = (sample >> 24) & 0xff;
112                 // data [ctr++] = (sample >> 16) & 0xff;
113                 data [ctr++] = (sample >>  8) & 0xff;
114                 data [ctr++] =  sample        & 0xff;
115         }
116         return true;
117 }
118
119
120 /* Write a 512-byte block to flash.  It is assumed that this
121  * is done sequentially; any special treatment for a header
122  * page will be done by the bottom layer, not the top.
123  * The return value indicates success.
124  */
125 bool boot_flash_write (uint16_t blocknr, uint8_t data [512]) {
126         return false;
127 }
128
129
130 /* Retrieve the current phone's MAC address from Flash.
131  */
132 void bottom_flash_get_mac (uint8_t mac [6]) {
133         uint32_t flashidx = flash_offset_mymac;
134         uint16_t ctr = 0;
135         while (ctr < 6) {
136                 uint16_t sample = flash_16 [flashidx];
137                 flashidx++;
138                 mac [ctr++] = (sample >> 8) & 0xff;
139                 mac [ctr++] =  sample       & 0xff;
140         }
141 }
142
143
144
145 /******** TLV320AIC20K PROGRAMMING ACCESS OVER I2C ********/
146
147
148 /* The codec can be programmed over I2C, so the low-level routines
149  * for driving the codec end up passing bytes over I2C.  The
150  * procedure of cycling through subregisters is not performed here.
151  */
152
153 void tlv320aic2x_setreg (uint8_t channel, uint8_t reg, uint8_t val) {
154         // Wait as long as the bus is busy
155 bottom_led_set (LED_IDX_MESSAGE, 1);
156         while (I2CSTR & REGVAL_I2CSTR_BB) {
157                 ;
158         }
159 // bottom_printf ("I2C.pre  = 0x%04x,0x%04x\n", (intptr_t) I2CSTR, (intptr_t) I2CMDR);
160         // Set transmission mode for 2 bytes to "channel"
161         I2CSAR = 0x40 | channel;
162         //TODO// I2CSAR = 0x00; // Broadcast
163         I2CCNT = 2;
164         I2CDXR = reg;
165         // Send the register index
166         // Initiate the transfer by setting STT and STP flags
167         I2CMDR = REGVAL_I2CMDR_TRX | REGVAL_I2CMDR_MST | REGVAL_I2CMDR_STT | REGVAL_I2CMDR_STP | REGVAL_I2CMDR_NORESET | REGVAL_I2CMDR_FREE | REGVAL_I2CMDR_BC_8;
168 // bottom_printf ("I2C.set  = 0x%04x,0x%04x\n", (intptr_t) I2CSTR, (intptr_t) I2CMDR);
169         // Wait for the START condition to occur
170 // bottom_led_set (LED_IDX_HANDSET, 1);
171         while (I2CMDR & REGVAL_I2CMDR_STT) {
172                 ;
173         }
174 // bottom_printf ("I2C.stt  = 0x%04x,0x%04x\n", (intptr_t) I2CSTR, (intptr_t) I2CMDR);
175 // bottom_led_set (LED_IDX_HANDSET, 0);
176         // Wait until the I2C bus is ready, then send the value
177 // bottom_led_set (LED_IDX_SPEAKERPHONE, 1);
178         while (!(I2CSTR & REGVAL_I2CSTR_XRDY)) {
179                 if (I2CSTR & REGVAL_I2CSTR_NACK) {
180                         // bottom_printf ("I2C received NACK\n");
181                         I2CSTR = REGVAL_I2CSTR_NACK;
182                         I2CMDR = REGVAL_I2CMDR_MST | REGVAL_I2CMDR_STP | REGVAL_I2CMDR_NORESET | REGVAL_I2CMDR_FREE | REGVAL_I2CMDR_BC_8;
183                         return;
184                 }
185         }
186 // bottom_printf ("I2C.xrdy = 0x%04x,0x%04x\n", (intptr_t) I2CSTR, (intptr_t) I2CMDR);
187 // bottom_led_set (LED_IDX_SPEAKERPHONE, 0);
188         I2CDXR = val;
189         // Wait for the STOP condition to occur
190         while (I2CMDR & REGVAL_I2CMDR_STP) {
191                 ;
192         }
193 // bottom_printf ("I2C.post = 0x%04x,0x%04x\n", (intptr_t) I2CSTR, (intptr_t) I2CMDR);
194 bottom_led_set (LED_IDX_MESSAGE, 0);
195 }
196
197 uint8_t tlv320aic2x_getreg (uint8_t channel, uint8_t reg) {
198         uint8_t val;
199 uint32_t ctr;
200 bottom_led_set (LED_IDX_MESSAGE, 1);
201 // bottom_led_set (LED_IDX_HANDSET, 0);
202         // Wait as long as the bus is busy
203         while (I2CSTR & REGVAL_I2CSTR_BB) {
204                 ;
205         }
206         // Set transmission mode for 1 byte to "channel"
207         I2CSAR = 0x40 | channel;
208         //TODO// I2CSAR = 0x00; // Broadcast
209         I2CCNT = 1;
210         I2CDXR = reg;
211         // Send the register index
212         // Initiate the transfer by setting STT flag, but withhold STP
213         I2CMDR = REGVAL_I2CMDR_TRX | REGVAL_I2CMDR_MST | REGVAL_I2CMDR_STT | /* REGVAL_I2CMDR_STP | */ REGVAL_I2CMDR_NORESET | REGVAL_I2CMDR_FREE | REGVAL_I2CMDR_BC_8;
214         // Wait until the START condition has occurred
215         while (I2CMDR & REGVAL_I2CMDR_STT) {
216                 ;
217         }
218         // ...send address and write mode bit...
219 // bottom_led_set (LED_IDX_HANDSET, 1);
220         // Wait until ready to setup for receiving
221         // while (I2CMDR & REGVAL_I2CMDR_STP) {
222         while (I2CSTR & (REGVAL_I2CSTR_XRDY | REGVAL_I2CSTR_XSMT) != (REGVAL_I2CSTR_XRDY | REGVAL_I2CSTR_XSMT)) {
223                 if (I2CSTR & (REGVAL_I2CSTR_NACK | REGVAL_I2CSTR_AL)) {
224                         I2CSTR = REGVAL_I2CSTR_NACK | REGVAL_I2CSTR_AL;
225                         I2CMDR = REGVAL_I2CMDR_MST | REGVAL_I2CMDR_STP | REGVAL_I2CMDR_NORESET | REGVAL_I2CMDR_FREE | REGVAL_I2CMDR_BC_8;
226                         return 0;
227                 }
228         }
229 // bottom_led_set (LED_IDX_HANDSET, 0);
230         I2CCNT = 1;
231         // Restart with STT flag, also permit stop with STP; do not set TRX
232         I2CMDR = REGVAL_I2CMDR_MST | /* REGVAL_I2CMDR_STT | */ REGVAL_I2CMDR_STP | REGVAL_I2CMDR_NORESET | REGVAL_I2CMDR_FREE | REGVAL_I2CMDR_BC_8;
233         // ...recv val...
234         while (!(I2CSTR & REGVAL_I2CSTR_RRDY)) {
235 #if 0
236                 if (I2CSTR & REGVAL_I2CSTR_NACK) {
237                         I2CSTR = REGVAL_I2CSTR_NACK;
238                         // I2CMDR = REGVAL_I2CMDR_MST | REGVAL_I2CMDR_STP | REGVAL_I2CMDR_NORESET | REGVAL_I2CMDR_FREE | REGVAL_I2CMDR_BC_8;
239                         // return 0;
240                 }
241 #endif
242                 ;
243         }
244         val = I2CDRR;
245 bottom_led_set (LED_IDX_MESSAGE, 0);
246         return val;
247 }
248
249
250 /******** TLV320AIC20K DATA ACCESS OVER MCBSP1 ********/
251
252
253 #define BUFSZ (80*24)
254
255 static volatile int16_t samplebuf_play   [BUFSZ];
256 static volatile int16_t samplebuf_record [BUFSZ];
257
258 static uint16_t samplebuf_blocksize = 80;
259 static uint16_t samplebuf_wrapindex = BUFSZ;
260
261 /* The buffer is a contiguous array of samples, made accessible
262  * to the top layer per block.  Upon setting sample rate and
263  * block size, all pointers start at the beginning of the buffer.
264  * While processing, the pointers advance with one blocksize at
265  * a time; they wrap around if there is not enough space left to
266  * cover a complete block within the bounds of the sample buffer.
267  *
268  * The buffer has three types of areas, each with their own
269  * consumer/producer relationships.  The areas are the same for
270  * the playback and recording buffer.  They are:
271  *  - playable: Can be filled be the codec for playback
272  *  - dmaready: Can be played/recorded through lockstep DMA
273  *  - recordable: Can be processed by the codec in recording
274  * Each of these areas is marked with an index pointer; their
275  * ends +1 are marked by another index pointer, as follows:
276  *
277  *      AREA            START   END+1
278  *      playable        play0   rec0
279  *      dmaready        dma0    play0
280  *      recordable      rec0    dma0
281  *
282  * DMA is possible if the dmaready area is non-empty, so if
283  * dma0 != play0.  After DMA has transferred a block,
284  * the dma0 pointer is incremented, and this is checked.
285  *
286  * bottom_record_claim() succeeds if rec0 != dma0, and when
287  * bottom_record_release() is called, rec0 increments.  Note
288  * that bottom_echo_claim() applies the same condition, but
289  * it returns the rec0 offset of the playbuf, instead of the
290  * rec0 offset in the recbuf as is returned by record_claim.
291  *
292  * bottom_play_claim() succeeds if play0 != rec0 *or* if the
293  * buffer is empty, which is noticed if DMA is not active. This
294  * means that playback is the first thing to start when a new
295  * set of index pointers is setup with zero values.  When the
296  * bottom_play_release() is called, play0 increments, and the
297  * DMA conditions are evaluated.
298  */
299
300 volatile bool dma_active = false;
301 /*TODO:static*/ volatile uint16_t bufofs_play0 = 0;
302 /*TODO:static*/ volatile uint16_t bufofs_dma0  = 0;
303 /*TODO:static*/ volatile uint16_t bufofs_rec0  = 0;
304
305
306 inline void bottom_bufferdma_progress (uint8_t chan) {
307         bool recordinghint = (bufofs_dma0 == bufofs_rec0);
308         bufofs_dma0 = (bufofs_dma0 + samplebuf_blocksize) % samplebuf_wrapindex;
309         if (bufofs_dma0 == bufofs_play0) {
310                 SPCR2_1 &= ~REGVAL_SPCR2_FRST_NOTRESET;         // Stop DMA
311                 dma_active = false;
312         }
313         if (recordinghint) {
314                 top_codec_can_record (chan);
315         }
316 }
317
318 int16_t *bottom_play_claim (uint8_t chan) {
319         if ((!dma_active) || (bufofs_play0 != bufofs_rec0)) {
320                 return (int16_t *) &samplebuf_play [bufofs_play0];
321         } else {
322                 return NULL;
323         }
324 }
325
326 void bottom_play_release (uint8_t chan) {
327         bool dmahint = (bufofs_play0 == bufofs_dma0);
328         bufofs_play0 = (bufofs_play0 + samplebuf_blocksize) % samplebuf_wrapindex;
329         if (dmahint) {
330                 //TODO// Following 5 lines can be done much earlier
331                 (void) DRR1_1;  // Flag down RFULL
332                 (void) DRR1_1;
333                 DMACCR_0 |= REGVAL_DMACCR_EN;
334                 DXR1_1 = DXR1_1;        // Flag down XEMPTY
335                 DMACCR_1 |= REGVAL_DMACCR_EN;
336                 SPCR2_1 |= REGVAL_SPCR2_FRST_NOTRESET;          // Start DMA
337                 dma_active = true;
338         }
339 }
340
341 int16_t *bottom_record_claim (uint8_t chan) {
342         if (bufofs_rec0 != bufofs_dma0) {
343                 return (int16_t *) &samplebuf_record [bufofs_rec0];
344         } else {
345                 return NULL;
346         }
347 }
348
349 int16_t *bottom_echo_claim (uint8_t chan) {
350         if (bufofs_rec0 != bufofs_dma0) {
351                 return (int16_t *) &samplebuf_play [bufofs_rec0];
352         } else {
353                 return NULL;
354         }
355 }
356
357 void bottom_record_release (uint8_t chan) {
358         bool playbackhint = (bufofs_rec0 == bufofs_play0);
359         bufofs_rec0 = (bufofs_rec0 + samplebuf_blocksize) % samplebuf_wrapindex;
360         if (playbackhint) {
361                 top_codec_can_play (chan);
362         }
363 }
364
365 static int TODO_setratectr = 0;
366
367 /* Set a frequency divisor for the intended sample rate */
368 //TODO// Not all this code is properly split between generic TLV and specific BT200
369 void tlv320aic2x_set_samplerate (uint8_t chan, uint32_t samplerate) {
370         uint16_t m, n, p;
371         SPCR2_1 |= REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
372 { uint32_t ctr = 100; while (ctr-- > 0) ; }
373         SPCR1_1 |= REGVAL_SPCR1_RRST_NOTRESET;
374         SPCR2_1 |= REGVAL_SPCR2_XRST_NOTRESET;
375 { uint32_t ctr = 10000; while (ctr-- > 0) ; }
376         DXR1_1 = DXR1_1;        // Flag down XEMPTY
377 tlv320aic2x_setreg (chan, 3, 0x31);     // Channel offline
378 { uint32_t ctr = 1000; while (ctr-- > 0) ; }
379         (void) DRR1_1;          // Flag down RFULL
380         (void) DRR1_1;
381         // Determine the dividors m, n and p
382         n = 1;
383         p = 2;
384         m = ( 30720000 / 16 ) / ( n * p * samplerate );
385         if ((m & 0x03) == 0x00) {
386                 // Save PLL energy without compromising accuracy
387                 p = 8;          // Factor 2 -> 8 so multiplied by 4
388                 m >>= 2;        // Divide by 4
389         }
390         while (m > 128) {
391                 m >>= 1;
392                 n <<= 1;
393         }
394 { uint8_t ip4 [4]; ip4 [0] = m; ip4 [1] = n; ip4 [2] = p; ip4 [3] = ++TODO_setratectr; bottom_show_ip4 (APP_LEVEL_CONNECTING, ip4); }
395 #ifdef CONFIG_FUNCTION_NETCONSOLE
396 bottom_printf ("TLV320AIC20K setting: M=%d, N=%d, P=%d\n", (intptr_t) m, (intptr_t) n, (intptr_t) p);
397 #endif
398         m &= 0x7f;
399         n &= 0x0f;      // Ignore range problems?
400         p &= 0x07;
401         // With the codec up and running, configure the sample rate
402         tlv320aic2x_setreg (chan, 4, 0x00 | (n << 3) | p);
403         tlv320aic2x_setreg (chan, 4, 0x80 | m);
404 { uint32_t ctr = 1000; while (ctr-- > 0) ; }
405 // #ifndef TODO_FS_ONLY_DURING_SOUND_IO
406         // SPCR2_1 |= REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
407         // SPCR1_1 |= REGVAL_SPCR1_RRST_NOTRESET;
408         // SPCR2_1 |= REGVAL_SPCR2_XRST_NOTRESET;
409         SPCR1_1 &= ~REGVAL_SPCR1_RRST_NOTRESET;
410         SPCR2_1 &= ~REGVAL_SPCR2_XRST_NOTRESET;
411 { uint32_t ctr = 10000; while (ctr-- > 0) ; }
412         SPCR2_1 &= ~ ( REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET );
413 { uint32_t ctr = 10000; while (ctr-- > 0) ; }
414         // SPCR2_1 &= ~ ( REGVAL_SPCR2_FRST_NOTRESET );
415 { uint32_t ctr = 10000; while (ctr-- > 0) ; }
416 // #endif
417         samplerate = 12288000 / samplerate;
418         if (samplerate >= 4096) {
419                 samplerate = 4096;
420         } else if (samplerate == 0) {
421                 samplerate = 1;
422         }
423         SRGR2_1 = REGVAL_SRGR2_CLKSM | REGVAL_SRGR2_FSGM | (samplerate - 1);
424 // #ifndef TODO_FS_ONLY_DURING_SOUND_IO
425         // SPCR2_1 |= REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
426         SPCR2_1 |= REGVAL_SPCR2_GRST_NOTRESET;
427 tlv320aic2x_setreg (chan, 3, 0x01);     // Channel online
428 { uint32_t ctr = 1000; while (ctr-- > 0) ; }
429         // tlv320aic2x_setreg (chan, 4, 0x00 | (n << 3) | p);
430         // tlv320aic2x_setreg (chan, 4, 0x80 | m);
431 // { uint32_t ctr = 10000; while (ctr-- > 0) ; }
432         SPCR1_1 |= REGVAL_SPCR1_RRST_NOTRESET;
433         SPCR2_1 |= REGVAL_SPCR2_XRST_NOTRESET;
434 { uint32_t ctr = 1000; while (ctr-- > 0) ; }
435         //NOT_FOR_NEW_STYLE_BUFFERS// SPCR2_1 |= REGVAL_SPCR2_FRST_NOTRESET;
436 { uint32_t ctr = 10000; while (ctr-- > 0) ; }
437         DXR1_1 = DXR1_1;        // Flag down XEMPTY
438         (void) DRR1_1;  // Flag down RFULL
439         (void) DRR1_1;
440 { uint32_t ctr = 10000; while (ctr-- > 0) ; }
441 // #endif
442 }
443
444 void bottom_soundchannel_set_samplerate (uint8_t chan, uint32_t samplerate,
445                         uint8_t blocksize, uint8_t upsample_play, uint8_t downsample_record) {
446         //
447         // Setup the buffersize of the sample buffers
448         samplebuf_blocksize = blocksize;
449         samplebuf_wrapindex = (BUFSZ / blocksize) * blocksize;
450         //
451         // Setup hardware with the requested sample rate (but no FRST generated)
452         tlv320aic2x_set_samplerate (chan, samplerate);
453         //
454         // Setup buffer index pointers at the start; effectively clearing all
455         dma_active = false;
456         bufofs_play0 = 0;
457         bufofs_dma0  = 0;
458         bufofs_rec0  = 0;
459 }
460
461 /* A full frame of 64 samples has been recorded.  See if space exists for
462  * another, otherwise disable DMA until a dmahint_play() restarts it.
463  * TODO: No processing needed for RX_DMA_IRQ, as TX_DMA_IRQ comes later.
464  */
465 interrupt void tic55x_dmac0_isr (void) {
466 #ifdef PREFER_OLD_STUFF
467         uint16_t irq = DMACSR_0;        // Note causes and clear
468         tic55x_top_has_been_interrupted = true;
469         if ((available_record += 64) > (BUFSZ - 64)) {
470                 SPCR2_1 &= ~REGVAL_SPCR2_XRST_NOTRESET;
471                 SPCR2_1 |=  REGVAL_SPCR2_XRST_NOTRESET;
472                 DMACCR_0 &= ~REGVAL_DMACCR_EN;
473 // #ifdef TODO_FS_ONLY_DURING_SOUND_IO
474                 // SPCR1_1 &= ~REGVAL_SPCR1_RRST_NOTRESET;
475                 // if ((SPCR2_1 & REGVAL_SPCR2_XRST_NOTRESET) == 0) {
476                         // SPCR2_1 &= ~ (REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET);
477                 // }
478 // #endif
479         }
480         if (available_record >= threshold_record) {
481                 top_codec_can_record (available_record);
482         }
483 #endif
484 }
485
486 /* A full frame of 64 samples has been played.  See if another is availabe,
487  * otherwise disable DMA until a dmahint_record() restarts it.
488  */
489 interrupt void tic55x_dmac1_isr (void) {
490 #ifdef PREFER_OLD_STUFF
491         uint16_t irq = DMACSR_1;        // Note causes and clear
492         uint16_t toplay;
493         tic55x_top_has_been_interrupted = true;
494         if ((available_play -= 64) < 64) {
495 // #ifdef TODO_FS_ONLY_DURING_SOUND_IO
496                 // SPCR2_1 &= ~REGVAL_SPCR2_XRST_NOTRESET;
497                 // if ((SPCR1_1 & REGVAL_SPCR1_RRST_NOTRESET) == 0) {
498                         // SPCR2_1 &= ~ (REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET);
499                 // }
500 // #endif
501                 DMACCR_1 &= ~REGVAL_DMACCR_EN;
502         }
503         toplay = BUFSZ - available_play;
504         if (BUFSZ - available_play >= threshold_play) {
505                 top_codec_can_play (available_play);
506         }
507 #endif
508         bottom_bufferdma_progress (0);
509 }
510
511 #ifdef PREFER_OLD_STUFF
512 /* Data has been removed from what was recorded.  As a result,
513  * it may be possible to restart DMA channel 1 if it was disabled.
514  */
515 void dmahint_record (void) {
516         if (! (DMACCR_0 & REGVAL_DMACCR_EN)) {
517                 if (available_record <= (BUFSZ - 64)) {
518                         if (!(DMACCR_0 & REGVAL_DMACCR_EN)) {
519                                 (void) DRR1_1;  // Flag down RFULL
520                                 (void) DRR1_1;
521                                 DMACCR_0 |= REGVAL_DMACCR_EN;
522 // #ifdef TODO_FS_ONLY_DURING_SOUND_IO
523                                 // SPCR1_1 |= REGVAL_SPCR1_RRST_NOTRESET;
524                                 // SPCR2_1 |= REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
525 // #endif
526                         }
527 // bottom_printf ("dmahint_record() enabled DMA from %d bytes out of %d\n", (intptr_t) available_record, (intptr_t) BUFSZ);
528                 }
529         }
530 }
531 #endif
532
533 #ifdef PREFER_OLD_STUFF
534 /* New data has been written for playback.  As a result, it may
535  * be possible to restart DMA channel 0 if it was disabled.
536  */
537 void dmahint_play (void) {
538         if ((available_play >= 64) && ! (DMACCR_1 & REGVAL_DMACCR_EN)) {
539                 DXR1_1 = DXR1_1;        // Flag down XEMPTY
540                 DMACCR_1 |= REGVAL_DMACCR_EN;
541 #ifdef CONFIG_FUNCTION_NETCONSOLE
542 bottom_printf ("dmahint_play() started playing DMA\n");
543 #endif
544 // #ifdef TODO_FS_ONLY_DURING_SOUND_IO
545                 // SPCR2_1 |= REGVAL_SPCR2_XRST_NOTRESET | REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
546 // #endif
547         }
548 //TODO:DEBUG// else bottom_printf ("dmahint_play() did not start playing -- available_play = %d\n", (intptr_t) available_play);
549 }
550 #endif
551
552
553
554 /******** HT162x LCD DRIVER LOW-LEVEL FUNCTIONS ********/
555
556
557 /* The program defines an array of LCDCMD_xxx to
558  * initialise the HT162x chip.  The array should be
559  * terminated with HT162x_LCDCMD_DONE.
560  */
561 extern uint16_t ht162x_setup_cmdseq [] = {
562         HT162x_LCDPREFIX_CMD,
563         HT162x_LCDCMD_LCDOFF,
564         HT162x_LCDCMD_NORMAL,
565         HT162x_LCDCMD_RC256K,
566         HT162x_LCDCMD_SYSEN,
567         HT162x_LCDCMD_LCDON,
568         HT162x_LCDCMD_TIMERDIS,
569         HT162x_LCDCMD_WDTDIS,
570         HT162x_LCDCMD_TONEOFF,
571         HT162x_LCDCMD_BIAS3_4,
572         HT162x_LCDCMD_TONE2K,
573         // Terminate the sequence:
574         HT162x_LCDCMD_DONE
575 };
576
577
578 /* Chip-enable or -disable the LCD driver */
579 void ht162x_chipselect (bool selected) {
580         if (selected) {
581                 IODATA &= ~ (1 << 1);
582         } else {
583                 IODATA |=   (1 << 1);
584         }
585 }
586
587
588 /* Send out a databit for the LCD driver, but do not clock it in */
589 static uint16_t kbdisp_outbuf = 0x0000;
590 void ht162x_databit_prepare (bool databit) {
591         if (databit) {
592                 kbdisp_outbuf &= ~0x4040;
593                 kbdisp_outbuf |=  0x8080;
594         } else {
595                 kbdisp_outbuf &= ~0xc0c0;
596         }
597         kbdisp = kbdisp_outbuf;
598 }
599
600 /* Clock in the database that was prepared for the LCD driver */
601 void ht162x_databit_commit (void) {
602         kbdisp_outbuf |= 0x4040;
603         kbdisp = kbdisp_outbuf;
604 }
605
606
607 /******** LCD-SPECIFIC FORM PAINTING ROUTINES ********/
608
609
610 /* Digit notations on the LCD's 7 segment displays */
611 uint8_t lcd7seg_digits [10] = {
612         0xaf, 0xa0, 0xcb, 0xe9, 0xe4,   // 01234
613         0x6d, 0x6f, 0xa8, 0xef, 0xed    // 56789
614 };
615
616 /* Alphabetic notations on the LCD's 7 segment displays */
617 uint8_t lcd7seg_alpha [26] = {
618         0xee, 0x67, 0x0f, 0xe3, 0x4f,   // AbCdE
619         0x4e, 0x2f, 0xe6, 0x06, 0xa1,   // FGHIJ
620         0x6e, 0x07, 0x6a, 0x62, 0x63,   // kLMno
621         0xce, 0xec, 0x42, 0x6d, 0x47,   // PQRST
622         0xa7, 0x23, 0x2b,               // Uvw
623         0x49, 0xe5, 0xc2
624 };
625
626 /* Put a character into display byte idx, with ASCII code ch */
627 void ht162x_putchar (uint8_t idx, uint8_t ch, bool notify) {
628         uint8_t chup = ch & 0xdf;
629         uint8_t lcd7seg;
630         if ((ch >= '0') && (ch <= '9')) {
631                 lcd7seg = lcd7seg_digits [ch - '0'];
632         } else if ((chup >= 'A') && (chup <= 'Z')) {
633                 lcd7seg = lcd7seg_alpha [chup - 'A'];
634         } else if (chup == 0x00) {
635                 lcd7seg = 0x00;  // space for chup one of 0x00 and 0x20
636         } else {
637                 lcd7seg = 0x40;  // dash
638         }
639         ht162x_dispdata [idx] = (ht162x_dispdata [idx] & 0x10) | lcd7seg;
640         if (notify) {
641                 ht162x_dispdata_notify (idx, idx);
642         }
643 }
644
645 uint8_t lcd_bars [8] = {
646         0x00, 0x20, 0x60, 0xe0, 0xe8, 0xec, 0xee, 0xef
647 };
648
649 /* Level indication for volume, showing the upper 3 bits of "level" */
650 void ht162x_audiolevel (uint8_t level) {
651         uint8_t bars = lcd_bars [level >> 5];
652         ht162x_dispdata [15] = (ht162x_dispdata [15] & 0x10) | bars;
653         ht162x_dispdata_notify (15, 15);
654 }
655
656 #define LCDSYM_NETWORK  14
657 #define LCDSYM_HANDSET  13
658 #define LCDSYM_SPEAKER  11
659 #define LCDSYM_FORWARD  10
660 #define LCDSYM_CLOCK    8
661 #define LCDSYM_LOCK     7
662 #define LCDSYM_BINARY   15
663 #define LCDSYM_CN1      4
664 #define LCDSYM_CN2      5
665 #define LCDSYM_HOUR10   0
666 #define LCDSYM_HMSEP    1
667 #define LCDSYM_AM       2
668 #define LCDSYM_PM       3
669 #define LCDSYM_DOT12    12
670 #define LCDSYM_DOT9     9
671 #define LCDSYM_DOT6     6
672
673 /* Special flag setting on the LCD, to flag conditions */
674 void ht162x_led_set (uint8_t lcdidx, led_colour_t col, bool notify) {
675         if (col) {
676                 ht162x_dispdata [lcdidx] |=  0x10;
677         } else {
678                 ht162x_dispdata [lcdidx] &= ~0x10;
679         }
680         if (notify) {
681                 ht162x_dispdata_notify (lcdidx, lcdidx);
682         }
683 }
684
685
686 /******** BOTTOM FUNCTIONS FOR LEDS AND BUTTONS ********/
687
688
689 /* Bottom-half operations to manipulate LED states */
690 void bottom_led_set (led_idx_t ledidx, led_colour_t col) {
691         switch (ledidx) {
692         case LED_IDX_HANDSET:
693                 ht162x_led_set (13, col, true);
694                 break;
695         case LED_IDX_SPEAKERPHONE:
696                 ht162x_led_set (11, col, true);
697                 break;
698         case LED_IDX_MESSAGE:
699                 if (col != 0) {
700                         asm (" bset xf");
701                 } else {
702                         asm (" bclr xf");
703                 }
704                 break;
705         case LED_IDX_BACKLIGHT:
706                 // Set bit DXSTAT=5 in PCR=0x2812 to 1/0
707                 if (col != 0) {
708                         PCR0 |=     1 << REGBIT_PCR_DXSTAT  ;
709                 } else {
710                         PCR0 &= ~ ( 1 << REGBIT_PCR_DXSTAT );
711                 }
712                 break;
713         default:
714                 break;
715         }
716 }
717
718
719 /* See if the phone (actually, the horn) is offhook */
720 bool bottom_phone_is_offhook (void) {
721         // The hook switch is attached to GPIO pin 5
722         return (IODATA & 0x20) != 0;
723 }
724
725
726 /* Scan to see if the top_hook_update() function must be called */
727 #if !defined NEED_HOOK_SCANNER_WHEN_ONHOOK || !defined NEED_HOOK_SCANNER_WHEN_OFFHOOK
728 #  error "The BT200 does not generate an interrupt on hook contact changes"
729 #endif
730 static bool bt200_offhook = false;
731 void bottom_hook_scan (void) {
732         if (bt200_offhook != bottom_phone_is_offhook ()) {
733                 bt200_offhook = !bt200_offhook;
734                 top_hook_update (bt200_offhook);
735         }
736 }
737
738 /* Scan to see if the top_button_press() or top_button_release()
739  * functions must be called.
740  *
741  * The following bits are written to activate one or more keyboard rows:
742  * D0..D4 are sent to the variable "kbdisp" which has the proper address.
743  * The intermediate variable "kbdisp_outbuf" stores a copy of the bits,
744  * and is shared with the LCD routines so unused bits must be retained.
745  *
746  * The following bits of McBSP0 are read from PCR0 as keyboard columns:
747  * C0=CLKRP, C1=CLKXP, C2=FSRP, C3=FSXP, C4=DRSTAT
748  *
749  * The following routine is designed from the assumption that the keyboard
750  * is operated a single key at a time; if not, then any response could be
751  * valid.  Note that we do not suppress multiple keys by sending an error
752  * code, or behaving like with key release.
753  */
754 #if !defined NEED_KBD_SCANNER_BETWEEN_KEYS || !defined NEED_KBD_SCANNER_DURING_KEYPRESS
755 #  error "The BT200 does not generate an interrupt on key changes"
756 #endif
757 #define KBD_COLUMNS_MASK ( REGVAL_PCR_CLKRP | REGVAL_PCR_CLKXP | REGVAL_PCR_FSRP | REGVAL_PCR_FSXP | REGVAL_PCR_DRSTAT )
758 static bool bt200_kbd_pressed = false;
759 static const buttoncode_t keynum2code  [25] = {
760         '1',            '2',            '3',            HAVE_BUTTON_MESSAGE,    HAVE_BUTTON_HOLD,
761         '4',            '5',            '6',            HAVE_BUTTON_TRANSFER,   HAVE_BUTTON_CONFERENCE,
762         '7',            '8',            '9',            HAVE_BUTTON_FLASH,      HAVE_BUTTON_MUTE,
763         '*',            '0',            '#',            HAVE_BUTTON_SEND,       HAVE_BUTTON_SPEAKER,
764         HAVE_BUTTON_DOWN, HAVE_BUTTON_UP, HAVE_BUTTON_CALLERS, HAVE_BUTTON_CALLED, HAVE_BUTTON_MENU
765 };
766 void bottom_keyboard_scan (void) {
767         uint16_t scan;
768         scan = PCR0 & KBD_COLUMNS_MASK;
769         if (bt200_kbd_pressed) {
770                 // Respond if the key is released
771                 if (scan == KBD_COLUMNS_MASK) {
772                         bt200_kbd_pressed = false;
773                         kbdisp_outbuf &= 0xe0e0;                // Make D0..D4 low
774                         kbdisp = kbdisp_outbuf;
775                         top_button_release ();
776                 }
777         } else {
778                 // Respond if a key is being pressed
779                 if (scan != KBD_COLUMNS_MASK) {
780                         uint16_t row;
781                         for (row = 0; row < 5; row++) {
782                                 kbdisp_outbuf |=   0x1f1f;      // Make D0..D4 high
783                                 kbdisp_outbuf &= ~(0x0101 << row); // Set D$row low
784                                 kbdisp = kbdisp_outbuf;
785                                 { volatile int pause = 5; while (pause > 0) pause--; }
786                                 scan = PCR0 & KBD_COLUMNS_MASK;
787                                 if (scan != KBD_COLUMNS_MASK) {
788                                         uint16_t col;
789                                         for (col = 0; col < 5; col++) {
790                                                 if (! (scan & (0x01 << col))) {
791                                                         uint16_t keynum = row * 5 + col;
792                                                         buttonclass_t bcl = ((row <= 3) && (col <= 2))? BUTCLS_DTMF: BUTCLS_FIXED_FUNCTION;
793                                                         buttoncode_t  cde = keynum2code  [keynum];
794                                                         bt200_kbd_pressed = true;
795                                                         top_button_press (bcl, cde);
796                                                         return;
797                                                 }
798                                         }
799                                 }
800                         }
801                         // Failed, usually due to an I/O glitch
802                         kbdisp_outbuf &= 0xe0e0;                // Make D0..D4 low
803                         kbdisp = kbdisp_outbuf;
804                 }
805         }
806 }
807
808
809 /******** BOTTOM FUNCTIONS FOR FORMATTING / PRINTING INFORMATION ********/
810
811
812 /* Send an elapsed period (not a wallclock time) to the display.
813  * For BT200, this is shown in the top digits as MM:SS or as HH:MM.
814  * Note that there are 2 positions, and the first digit can only show a 1.
815  */
816 static app_level_t bt200_period_level = APP_LEVEL_ZERO;
817 void bottom_show_period (app_level_t level, uint8_t h, uint8_t m, uint8_t s) {
818         if (bt200_period_level > level) {
819                 // Ignore those lower values, as this is highly time-dependent
820                 return;
821         }
822         bt200_period_level = level;
823         if ((h == 0) && (m <= 19)) {
824                 h = m;
825                 m = s;
826         }
827         ht162x_led_set (2, false,   false); // "AM" off
828         ht162x_led_set (3, false,   false); // "PM" off
829         ht162x_led_set (1, true,    false); // ":" in "xx:xx"
830         ht162x_led_set (0, h >= 10, false); // "1" in "1x:xx"
831         ht162x_putchar (0, (h %  10) + '0', false);
832         ht162x_putchar (1, (m /  10) + '0', false);
833         ht162x_putchar (2, (m %  10) + '0', false);
834         ht162x_dispdata_notify (0, 3);
835 }
836
837 /* The level of the main portion of the display, along with an array
838  * with the contents at each level
839  */
840 static bt200_displine_level = APP_LEVEL_ZERO;
841 static bool    bt200_level_active [APP_LEVEL_COUNT];
842 static uint8_t bt200_level_maintext [APP_LEVEL_COUNT] [12];
843 static uint8_t bt200_level_dotbits  [APP_LEVEL_COUNT];
844
845 /* Internal routine to move a display level to the display.
846  * Note that no "led" style bits other than the dots in the main
847  * line are influenced.
848  */
849 static void bt200_displine_showlevel (app_level_t level) {
850         uint8_t i;
851         for (i = 0; i < 12; i++) {
852                 ht162x_putchar (14 - i, bt200_level_maintext [level] [i], false);
853         }
854         ht162x_led_set (12, (bt200_level_dotbits [level] & 0x01), false);
855         ht162x_led_set ( 9, (bt200_level_dotbits [level] & 0x02), false);
856         ht162x_led_set ( 6, (bt200_level_dotbits [level] & 0x04), false);
857         ht162x_dispdata_notify (3, 14);
858 }
859
860 /* Internal routine to send a string to the display, either with or
861  * without setting the various dots.  The dots are coded in bits
862  * 0, 1 and 2 of the dotbits parameter, from left to right.
863  */
864 static void bt200_display_showtxt (app_level_t level, char *txt, uint8_t dotbits) {
865         // 1. Print text to the proper level
866         int idx = 0;
867         while ((idx < 12) && *txt) {
868                 bt200_level_maintext [level] [idx++] = *txt++;
869         }
870         while (idx < 12) {
871                 bt200_level_maintext [level] [idx++] = ' ';
872         }
873         bt200_level_dotbits [level] = dotbits;
874         bt200_level_active [level] = true;
875         // 2. If the level is not exceeded by the current, reveal it
876         if (bt200_displine_level <= level) {
877                 bt200_displine_showlevel (level);
878                 bt200_displine_level = level;
879         }
880 }
881
882
883 /* Stop displaying content at the specified level.  In some cases, older
884  * content may now pop up, in others the display could get cleared.
885  */
886 void bottom_show_close_level (app_level_t level) {
887         if (bt200_period_level == level) {
888                 bt200_period_level = APP_LEVEL_ZERO;
889                 ht162x_led_set (0, false, false);
890                 ht162x_led_set (1, false, false);
891                 ht162x_dispdata [0] = 0x00;
892                 ht162x_dispdata [1] = 0x00;
893                 ht162x_dispdata [2] = 0x00;
894                 ht162x_dispdata_notify (0, 2);
895         }
896         if (bt200_displine_level == level) {
897                 bt200_level_active [level] = false;
898                 memset (bt200_level_maintext [level], ' ', 12);
899                 while ((bt200_displine_level > APP_LEVEL_ZERO)
900                                 && !bt200_level_active [bt200_displine_level]) {
901                         bt200_displine_level--;
902                 }
903                 bt200_displine_showlevel (bt200_displine_level);
904         }
905 }
906
907 /* Print an IPv4 address on the display */
908 void bottom_show_ip4 (app_level_t level, uint8_t bytes [4]) {
909         uint8_t idx;
910         char ip [12];
911         char *ipptr = ip;
912         for (idx = 0; idx < 4; idx++) {
913                 *ipptr++ = '0' +  (bytes [idx] / 100);
914                 *ipptr++ = '0' + ((bytes [idx] % 100) / 10);
915                 *ipptr++ = '0' +  (bytes [idx] % 10);
916         }
917         bt200_display_showtxt (level, ip, 0x07);
918 }
919
920 /* Print an IPv6 address, as far as this is possible, on the display
921  *  - Remove the prefix /64 as it is widely known
922  *  -TODO- If middle word is 0xfffe, remove it, display the rest, set dot #2
923  *  -TODO- If first word is 0x0000, remove it, display the rest, set dot #1
924  *  -TODO- If last word is 0x0001, remove it, display the rest, set dot #3
925  *  - If nothing else is possible, use 6 bits per digit, dots and last digit blanc
926 void bottom_show_ip6 (app_level_t level, uint16_t words [8]) {
927         // TODO: Extra cases; for now, just dump 6 bits per 7-segment display
928         uint8_t idxi;
929         uint8_t idxo;
930         uint8_t shfi;
931         uint8_t shfo;
932         ht162x_led_set (12, 0, false);
933         ht162x_led_set ( 9, 0, false);
934         ht162x_led_set ( 6, 0, false);
935         for (idxo = 14; idxo >= 3; idxo--) {
936                 ht162x_dispdata [idxo] &= 0x10;
937         }
938         shfi = 6;
939         shfo = 4;
940         idxi = 4;
941         idxo = 14;
942         while (idxi < 8) {
943                 uint8_t twobits = (words [idxi] >> shfi) & 0x03;
944                 twobits << shfo;
945                 if (twobits & 0x10) {
946                         twobits += 0x80 - 0x10; // bit 7 replaces bit 4
947                 }
948                 ht162x_dispdata [idxo] |= (twobits << shfo);
949                 if (shfi > 0) {
950                         shfi -= 2;
951                 } else {
952                         shfi = 6;
953                         idxi++;
954                 }
955                 if (shfo > 0) {
956                         shfo -= 2;
957                 } else {
958                         shfo = 5;
959                         idxo--;
960                 }
961         }
962         ht162x_dispdata_notify (14, 3);
963 }
964
965 /* A list of fixed messages, matching the fixed_msg_t values */
966
967 static char *bt200_fixed_messages [FIXMSG_COUNT] = {
968         "offline",
969         "registering",
970         "ready",
971         "bootload",
972         "sending call",
973         "ringing",
974         "call ended",
975 };
976
977 /* Print a fixed message on the main line of the display */
978 void bottom_show_fixed_msg (app_level_t level, fixed_msg_t msg) {
979         if (msg < FIXMSG_COUNT) {
980                 bt200_display_showtxt (level, bt200_fixed_messages [msg], 0x00);
981         }
982 }
983
984 /* Print a notification of the number of new / old voicemails */
985 void bottom_show_voicemail (app_level_t level, uint16_t new, uint16_t old) {
986         char msg [12];
987         if (new > 999) {
988                 new = 999;
989         }
990         memcpy (msg, "xxx messages", 12);
991         msg [0] =  new / 100;
992         msg [1] = (new % 100) / 10;
993         msg [2] =  new        % 10;
994         bt200_display_showtxt (level, msg, 0x00);
995 }
996
997 /******** BOTTOM LEVEL MAIN PROGRAM ********/
998
999 /* Setup the connectivity of the TIC55x as used on Grandstream BT20x */
1000 void main (void) {
1001         uint16_t idx;
1002         led_colour_t led = LED_STABLE_ON;
1003         //
1004         // PLL setup: Crystal is 16.384 MHz, increase that 15x
1005         // 1. Switch to bypass mode by setting the PLLEN bit to 0.
1006         PLLCSR &= ~REGVAL_PLLCSR_PLLEN;
1007         // 2. Set the PLL to its reset state by setting the PLLRST bit to 1.
1008         PLLCSR |= REGVAL_PLLCSR_PLLRST;
1009         // 3. Change the PLL setting through the PLLM and PLLDIV0 bits.
1010         PLLM = REGVAL_PLLM_TIMES_15;
1011         PLLDIV0 = REGVAL_PLLDIVx_DxEN | REGVAL_PLLDIVx_PLLDIVx_1;
1012         // 4. Wait for 1 µs.
1013         { int ctr = 1000; while (ctr--) ; }
1014         // 5. Release the PLL from its reset state by setting PLLRST to 0.
1015         PLLCSR &= ~REGVAL_PLLCSR_PLLRST;
1016         // 6. Wait for the PLL to relock by polling the LOCK bit or by setting up a LOCK interrupt.
1017         while ((PLLCSR & REGVAL_PLLCSR_LOCK) == 0) {
1018                 /* wait */ ;
1019         }
1020         // 7. Switch back to PLL mode by setting the PLLEN bit to 1.
1021         PLLCSR |= REGVAL_PLLCSR_PLLEN;
1022         PLLDIV1 = REGVAL_PLLDIVx_DxEN | REGVAL_PLLDIVx_PLLDIVx_2;
1023         PLLDIV2 = REGVAL_PLLDIVx_DxEN | REGVAL_PLLDIVx_PLLDIVx_4;
1024         PLLDIV3 = REGVAL_PLLDIVx_DxEN | REGVAL_PLLDIVx_PLLDIVx_4;
1025         //TODO// PLLDIV3 = REGVAL_PLLDIVx_DxEN | REGVAL_PLLDIVx_PLLDIVx_2;
1026         //TODO// PLLCSR |= REGVAL_PLLCSR_PLLEN;
1027         // Now we have:
1028         //      CPU clock is 245.76 MHz
1029         //      SYSCLK1   is 122.88 MHz
1030         //      SYSCLK2   is  61.44 MHz
1031         //
1032         // EMIF settings, see SPRU621F, section 2.12 on "EMIF Registers"
1033         //
1034         EGCR1 = 0xff7f;
1035         // EGCR2 = 0x0009; // ECLKOUT2-DIV-4
1036 // EGCR2 = 0x0001;      //ECLKOUT2-DIV-1//
1037 EGCR2 = 0x0005; //ECLKOUT2-DIV-2//
1038         // EGCR1 = ...;   // (defaults)
1039         // EGCR2 = ...;   // (defaults)
1040         // CESCR1 = ...;   // (defaults)
1041         // CESCR2 = ...;   // (defaults)
1042         //
1043         // CE0 selects the network interface
1044         // CE0_1 = 0xff03;   // DEFAULT 8-bit async (and defaults)
1045         // Fail: CE0_1 = 0xc112;   // 16-bit async, rd setup 2, rd strobe 1, rd hold 2
1046         // Fail: CE0_2 = 0x20a2;          // wr setup 2, wr strobe 2, wr hold 2, rd setup 2
1047         CE0_1 = 0x3f2f;
1048         CE0_2 = 0xffff;
1049         // CE0_2 = ...;   // (defaults)
1050         // CE0_SC1 = ...;   // (defaults)
1051         // CE0_SC2 = ...;   // (defaults)
1052         //
1053         // CE1 selects the flash chip
1054         //WORKED?// CE1_1 = 0xff13;   // 16-bit async (and defaults)
1055         CE1_1 = 0x0922;
1056         CE1_2 = 0x31f2;
1057         // CE1_2 = ...;   // (defaults)
1058         // CE1_SC1 = ...;   // (defaults)
1059         // CE1_SC2 = ...;   // (defaults)
1060         //
1061         // CE2 selects the SDRAM chips
1062         //WORKS?// CE2_1 = 0xff33;   // 32-bit SDRAM (and defaults)
1063         CE2_1 = 0xff37;
1064         //TEST// CE2_1 = 0xff13;   // 16-bit async (and defaults)
1065         // CE2_2 = ...;   // (defaults)
1066         // CE2_SC1 = ...;   // (defaults)
1067         // CE2_SC2 = ...;   // (defaults)
1068         // Possible: SDC1, SDC2, SDRC1, SDRC2, SDX1, SDX2
1069         SDC1 = 0x6ffe;
1070         SDC2 = 0x8712;
1071         SDRC1 = 0xf5dc;
1072         SDRC2 = 0xffff;
1073         SDX1 = 0xb809;
1074         CESCR1 = 0xfffc;
1075         //
1076         // CE3 selects the D-flipflops for keyboard and LCD
1077         CE3_1 = 0xff13;   // 16-bit async (and defaults)
1078         //BT200ORIG// CE3_1 = 0x0220;
1079         //BT200ORIG// CE3_2 = 0x0270;
1080         // CE3_2 = ...;   // (defaults)
1081         // CE3_SC1 = ...;   // (defaults)
1082         // CE3_SC2 = ...;   // (defaults)
1083         //
1084         // Setup output ports; reset TLV chip; reset message levels
1085 { uint32_t ctr = 10000; while (ctr-- > 0) ; }
1086         IODIR  |= (1 << 7) | (1 << 1);
1087         IODATA  =            (1 << 1);  // Updated below small delay
1088         { uint32_t ctr; for (ctr=0; ctr < 7 * (600 / 12); ctr++) /* Wait 7x MCLK */ ; }
1089         IODATA |= (1 << 7) | (1 << 1);  // See above small delay
1090         { uint32_t ctr; for (ctr=0; ctr < 132 * (600 / 12); ctr++) /* Wait at least 132 MCLK cycles */ ; }
1091         //
1092         // Setup McBSP1 for linking to TLV320AIC20K
1093         // Generate a CLKG at 12.288 MHz, and FS at 8 kHz
1094         // following the procedure of spru592e section 3.5
1095         //
1096         DXR1_1 = 0x0000;
1097         SPCR1_1 = 0x0000;       // Disable/reset receiver, required in spru592e
1098         SPCR2_1 = 0x0000;       // Disable/reset sample rate generator
1099         SRGR1_1 = REGVAL_SRGR1_FWID_1 | REGVAL_SRGR1_CLKGDIV_4;
1100         SRGR2_1 = REGVAL_SRGR2_CLKSM | REGVAL_SRGR2_FSGM | REGVAL_SRGR2_FPER_1535;
1101         //COPIED_BELOW// PCR1 = /*TODO: (1 << REGBIT_PCR_IDLEEN) | */ (1 << REGBIT_PCR_FSXM) /* | (1 << REGBIT_PCR_FSRM) */ | (1 << REGBIT_PCR_CLKXM) /* | (1 << REGBIT_PCR_CLKRM) */ | (1 << REGBIT_PCR_CLKXP) | (1 << REGBIT_PCR_CLKRP);
1102         PCR1 = (1 << REGBIT_PCR_FSXM) | (1 << REGBIT_PCR_CLKXM);
1103 { uint32_t ctr = 10000; while (ctr-- > 0) ; }
1104 // SPCR2_1 |= REGVAL_SPCR2_GRST_NOTRESET | REGVAL_SPCR2_FRST_NOTRESET;
1105         RCR1_1 = (0 << 8) | (2 << 5);   // Read  1 frame of 16 bits per FS
1106         XCR1_1 = (0 << 8) | (2 << 5);   // Write 1 frame of 16 bits per FS
1107         RCR2_1 = 0x0001;                // Read  with 1 clockcycle delay
1108         XCR2_1 = 0x0001;                // Write with 1 clockcycle delay
1109         //TODO:NOT-SPI-BUT-CONTINUOUS-CLOCK// SPCR1_1 |= REGVAL_SPCR1_CLKSTP_NODELAY;
1110         //
1111         // Setup I2C for communication with the TLV320AIC20K codec
1112         // Prescale SYSCLK2 down from 61.44 MHz to 10.24 MHz so it falls
1113         // in the required 7 Mhz to 12 MHz range; support a 100 kHz I2C bus
1114         // by setting low/high period to 51 such periods.
1115         // Note: The only peripheral TLV320AIC20K could go up to 900 kHz
1116         I2CMDR = REGVAL_I2CMDR_MST | /* reset to set PSC */  REGVAL_I2CMDR_FREE | REGVAL_I2CMDR_BC_8;
1117         I2CPSC = 5;
1118         I2CCLKH = 51 - 5;       /* TODO: 900 kHz is possible on TLV320AIC20K */
1119         I2CCLKL = 51 - 5;
1120         I2COAR = REGVAL_I2COAR;
1121         I2CMDR = REGVAL_I2CMDR_MST | REGVAL_I2CMDR_NORESET | REGVAL_I2CMDR_FREE | REGVAL_I2CMDR_BC_8;
1122         //
1123         // Setup DMA channel 0 for playing from DSP to TLV320AIC2x
1124         // Setup DMA channel 1 for recording from TLV320AIC2x to DSP
1125         //
1126         // Both channels have a block (their entire RAM buffer) comprising
1127         // of 25 frames, which each are 64 samples of 16 bits in size.
1128         // At 8 kHz sample rate, frames cause 125 interrupts per second;
1129         // at 48 kHz this rises to 750 (per channel), still comfortable.
1130         // The total buffer is 1600 samples of 16 bits long.  Each time a
1131         // frame send finishes, an interrupt checks if there is another
1132         // frame of 64 samples ready to go; if not, it will disable the
1133         // DMA channel.  Hint routines serve to restart DMA after that.
1134         // Conversely, the DMA interrupt handlers can make top-calls to
1135         // indicate that data is ready for reading or that space is
1136         // available for writing.
1137         // The settings below prepare DMA for continuous playing and
1138         // recording, but with the setup disabled until hinted.
1139         //
1140         DMAGCR = REGVAL_DMAGCR_FREE;
1141         DMAGTCR = 0x00;         // No timeout support
1142         DMACCR_0 = REGVAL_DMACCR_SRCAMODE_CONST | REGVAL_DMACCR_DSTAMODE_POSTINC | REGVAL_DMACCR_PRIO | REGVAL_DMACCR_SYNC_MCBSP1_REV | REGVAL_DMACCR_REPEAT | REGVAL_DMACCR_AUTOINIT;
1143         DMACCR_1 = REGVAL_DMACCR_SRCAMODE_POSTINC | REGVAL_DMACCR_DSTAMODE_CONST | REGVAL_DMACCR_PRIO | REGVAL_DMACCR_SYNC_MCBSP1_TEV | REGVAL_DMACCR_REPEAT | REGVAL_DMACCR_AUTOINIT;
1144         DMACICR_0 = REGVAL_DMACICR_FRAMEIE;
1145         DMACICR_1 = REGVAL_DMACICR_FRAMEIE;
1146         //TODO// DMACSDP_0 = REGVAL_DMACSDP_SRC_PERIPH | REGVAL_DMACSDP_DST_DARAM1 | REGVAL_DMACSDP_DATATYPE_16BIT;
1147         //TODO// DMACSDP_1 = REGVAL_DMACSDP_SRC_DARAM0 | REGVAL_DMACSDP_DST_PERIPH | REGVAL_DMACSDP_DATATYPE_16BIT;
1148         DMACSDP_0 = REGVAL_DMACSDP_SRC_PERIPH | REGVAL_DMACSDP_DST_EMIF | REGVAL_DMACSDP_DATATYPE_16BIT;
1149         DMACSDP_1 = REGVAL_DMACSDP_SRC_EMIF | REGVAL_DMACSDP_DST_PERIPH | REGVAL_DMACSDP_DATATYPE_16BIT;
1150         DMACSSAL_0 = ((intptr_t) &DRR1_1) <<  1;
1151         DMACSSAU_0 = ((intptr_t) &DRR1_1) >> 15;
1152         DMACDSAL_0 = (uint16_t) (((intptr_t) samplebuf_record) <<  1);
1153         DMACDSAU_0 = (uint16_t) (((intptr_t) samplebuf_record) >> 15);
1154         DMACSSAL_1 = (uint16_t) (((intptr_t) samplebuf_play)   <<  1);
1155         DMACSSAU_1 = (uint16_t) (((intptr_t) samplebuf_play)   >> 15);
1156         DMACDSAL_1 = ((intptr_t) &DXR1_1) <<  1;
1157         DMACDSAU_1 = ((intptr_t) &DXR1_1) >> 15;
1158 #if TRY_SOMETHING_ELSE_TO_GET_INTERRUPTS
1159         DMACEN_0 = 64;           /* 64 elements (samples) per frame (continue-checks) */
1160         DMACEN_1 = 64;
1161         DMACFN_0 = (BUFSZ / 64); /* 25 frames (continue-checks) per block (buffer) */
1162         DMACFN_1 = (BUFSZ / 64);
1163 #else
1164         DMACEN_0 = 64;
1165         DMACEN_1 = 64;
1166         DMACFN_0 = 1;
1167         DMACFN_1 = 1;
1168 #endif
1169         /* TODO? */
1170         //
1171         // Further initiation follows
1172         //
1173         asm (" bclr xf");  // Switch off MESSAGE LED
1174 { uint16_t ctr = 250; while (ctr > 0) { ctr--; } }      
1175         bottom_critical_region_begin (); // _disable_interrupts ();
1176         IER0 = IER1 = 0x0000;
1177         tic55x_setup_timers ();
1178         tic55x_setup_interrupts ();
1179         ht162x_setup_lcd ();
1180         tlv320aic2x_set_samplerate (0, 8000);
1181         tlv320aic2x_setup_sound ();
1182         ksz8842_setup_network ();
1183         // Enable INT0..INT3
1184         //TODO:TEST// IER0 |= 0x0a0c;
1185         //TODO:TEST// IER1 |= 0x0005;
1186         IER0 |= (1 << REGBIT_IER0_DMAC1) | (1 << REGBIT_IER0_INT0) | (1 << REGBIT_IER0_TINT0); // 0x0214;
1187         IER1 |= (1 << REGBIT_IER1_DMAC0); // 0x0004;
1188         PCR0 = (1 << REGBIT_PCR_XIOEN) | (1 << REGBIT_PCR_RIOEN);
1189
1190         for (idx = 0; idx < APP_LEVEL_COUNT; idx++) {
1191                 bt200_level_active [idx] = false;
1192         }
1193 #if 0
1194 {uint8_t idx, dig, bar;
1195 idx=0; dig=0; bar=0;
1196 memset (ht162x_dispdata, 0x00, sizeof (ht162x_dispdata));
1197 while (true) {
1198 uint32_t ctr;
1199 ht162x_putchar (14 - idx, (dig < 10)? (dig + '0'): (dig + 'A' - 11));
1200 ht162x_audiolevel ((bar < 8)? (bar << 5): ((14-bar) << 5));
1201 // bottom_led_set (LED_IDX_MESSAGE, LED_STABLE_OFF);
1202 ht162x_dispdata_notify (14 - idx, 14 - idx);
1203 ht162x_dispdata_notify (15, 15);
1204 // bottom_led_set (LED_IDX_MESSAGE, LED_STABLE_ON );
1205 idx = (idx + 1) % 12;
1206 dig = (dig + 1) % 38;
1207 bar = (bar + 1) % 14;
1208 ctr = 650000; while (ctr>0) ctr--;
1209 }
1210 }
1211 #endif
1212
1213         //TODO// IER0 = 0xdefc;
1214         //TODO// IER1 = 0x00ff;
1215 /* TODO: Iterate over flash partitions that can boot, running each in turn: */
1216         top_main ();
1217 }
1218