1 /*-------------------------------------------------------------------------
2 tinibios.c - startup and serial routines for the DS80C400 (tested on TINIM400)
4 Written By - Johan Knol, johan.knol@iduna.nl
6 Further hacked by Kevin Vigor with invaluable assistance from Bob Heise.
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
29 #define TIMED_ACCESS(sfr,value) { TA=0xaa; TA=0x55; sfr=value; }
31 // FIXME: Doesn't work, maybe?
32 static void _installInterrupt(void (*isrPtr)(void), unsigned char offset)
34 unsigned char xdata * vectPtr = (unsigned char xdata *) offset;
35 unsigned long isr = (unsigned long)isrPtr;
38 *vectPtr++ = (unsigned char)(isr >> 16);
39 *vectPtr++ = (unsigned char)(isr >> 8);
40 *vectPtr = (unsigned char)isr;
43 unsigned char _sdcc_external_startup(void)
48 // Do some blinking of the LED.
49 for (j = 0; j < 10; j++)
52 for (i = 0; i < 32767; i++)
57 for (i = 0; i < 32767; i++)
64 IE = 0; // Disable all interrupts.
67 ; save the 24-bit return address
73 mov _ESP,#0x00; reinitialize the stack
76 ; restore the 24-bit return address
82 // Stub: call rom_init here, then fixup IVT.
85 Serial0Init(1, 0); // baud argument ignored.
87 IE = 0x80; // Enable interrupts.
92 // now the serial0 stuff
94 // just to make the code more readable
95 #define S0RBS SERIAL_0_RECEIVE_BUFFER_SIZE
97 // this is a ring buffer and can overflow at anytime!
98 static volatile unsigned char receive0Buffer[S0RBS];
99 static volatile int receive0BufferHead=0;
100 static volatile int receive0BufferTail=0;
101 // no buffering for transmit
102 static volatile char transmit0IsBusy=0;
104 static data unsigned char serial0Buffered;
106 /* Initialize serial0.
108 Available baudrates are from 110 upto 115200 (using 16-bit timer 2)
109 If baud==0, the port is disabled.
111 If buffered!=0, characters received are buffered using an interrupt
114 void Serial0Init (unsigned long baud, unsigned char buffered) {
116 ES0 = 0; // disable serial channel 0 interrupt
118 // Need no port setup, done by boot rom.
122 // hack serial ISR in, no magic support for ISR routines yet.
124 // FIXME: this doesn't work, use only non-buffered mode!
126 _installInterrupt(Serial0IrqHandler, 0x23);
128 serial0Buffered=buffered;
131 RI_0=TI_0=0; // clear "pending" interrupts
132 ES0 = 1; // enable serial channel 0 interrupt
134 RI_0=0; // receive buffer empty
135 TI_0=1; // transmit buffer empty
139 void Serial0Baud(unsigned long baud) {
141 baud=-((long)OSCILLATOR/(32*baud));
144 TF2=0; // clear overflow flag
145 TR2=1; // start timer
148 void Serial0IrqHandler (void) interrupt 4 {
151 receive0Buffer[receive0BufferHead]=SBUF0;
152 receive0BufferHead=(receive0BufferHead+1)&(S0RBS-1);
153 if (receive0BufferHead==receive0BufferTail) {
154 /* buffer overrun, sorry :) */
155 receive0BufferTail=(receive0BufferTail+1)&(S0RBS-1);
165 char Serial0CharArrived(void) {
166 if (serial0Buffered) {
167 if (receive0BufferHead!=receive0BufferTail)
168 return receive0Buffer[receive0BufferTail];
176 void Serial0PutChar (char c)
178 if (serial0Buffered) {
179 while (transmit0IsBusy)
191 char Serial0GetChar (void)
194 if (serial0Buffered) {
195 while (receive0BufferHead==receive0BufferTail)
197 c=receive0Buffer[receive0BufferTail];
198 ES0=0; // disable serial interrupts
199 receive0BufferTail=(receive0BufferTail+1)&(S0RBS-1);
200 ES0=1; // enable serial interrupts
211 // FIXME: no ClockMilliSecondsDelay yet.
212 void Serial0SendBreak() {
214 ClockMilliSecondsDelay(2);
219 void Serial0Flush() {
220 ES0=0; // disable interrupts
221 receive0BufferHead=receive0BufferTail=0;
223 if (serial0Buffered) {
225 ES0=1; // enable interrupts