1 /*-------------------------------------------------------------------------
2 CPU depending Declarations
4 Written By - Dipl.-Ing. (FH) Michael Schmitt
6 mschmitt@mainz-online.de
7 michael.schmitt@t-online.de
9 Thanks to Josef Wolf <jw@raven.inka.de> for the serial io functions
12 This program is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by the
14 Free Software Foundation; either version 2, or (at your option) any
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 In other words, you are welcome to use, share and improve this program.
27 You are forbidden to forbid anyone else to use, share and improve
28 what you give them. Help stamp out software-hoarding!
29 -------------------------------------------------------------------------*/
31 // This file contains CPU depending utilities
32 // some of these parts are taken from sources made public by the sdcc project
33 // special thanks to sandeep for his great work and all other
35 // First some usseful definitions
39 // here is a definition of a single nop command as it has to be declared under keil-C and sdcc
41 #define NOP _asm nop _endasm
47 // ===========================================================================================
48 // Here are some CPU depending definitions that have to checked
50 #ifndef EXTENDED_CPU_IDLE
53 PCON |= 0x01; /* Setting IDL-Bit of Register PCON */
56 #define CpuIdle() PCON |= 0x01; PCON |= 0x20 // start the idle mode...
65 // ===========================================================================================
66 // Serial IO using the internal UART in interrupt mode
67 #ifdef SERIAL_VIA_INTERRUPT
69 #define SERIAL_IS_DEFINED
71 // Transmit Buffersize
72 #ifndef SERIAL_VIA_INTERRUPT_XBUFLEN
73 #error "SERIAL_VIA_INTERRUPT_XBUFLEN not defined using default"
74 #define SERIAL_VIA_INTERRUPT_XBUFLEN 8
77 // Receive Buffer Size
78 #ifndef SERIAL_VIA_INTERRUPT_RBUFLEN
79 #error "SERIAL_VIA_INTERRUPT_RBUFLEN not defined using default"
80 #define SERIAL_VIA_INTERRUPT_RBUFLEN 8
83 // for interrupt mode we implement a ring buffer
84 volatile xdata static unsigned char SERIAL_VIA_INTERRUPT_RBUF[SERIAL_VIA_INTERRUPT_RBUFLEN];
85 volatile xdata static unsigned char SERIAL_VIA_INTERRUPT_XBUF[SERIAL_VIA_INTERRUPT_XBUFLEN];
86 volatile static unsigned char SERIAL_VIA_INTERRUPT_RCNT;
87 volatile static unsigned char SERIAL_VIA_INTERRUPT_XCNT;
88 volatile static unsigned char SERIAL_VIA_INTERRUPT_RPOS;
89 volatile static unsigned char SERIAL_VIA_INTERRUPT_XPOS;
90 volatile static unsigned char SERIAL_VIA_INTERRUPT_BUSY;
92 #endif // SERIAL_VIA_INTERRUPT
94 #ifdef SERIAL_VIA_POLLING
95 #define SERIAL_IS_DEFINED
96 #endif // SERIAL_VIA_POLLING
98 #ifdef SERIAL_IS_DEFINED
99 // Here are some definitions about the desired serial interface
101 #error "CPUCLKHZ is not defined !"
104 #error "BAUDRATE is not defined !"
107 #define TIMER1MODE2RELOADVALUE (256-(1*CPUCLKHZ/32/12/BAUDRATE))
108 #endif // SERIAL_IS_DEFINED
110 #ifdef SERIAL_VIA_INTERRUPT
111 void ser_handler (void) interrupt 4
115 /* don't overwrite chars already in buffer */
116 if (SERIAL_VIA_INTERRUPT_RCNT < SERIAL_VIA_INTERRUPT_RBUFLEN)
117 SERIAL_VIA_INTERRUPT_RBUF [(SERIAL_VIA_INTERRUPT_RPOS+SERIAL_VIA_INTERRUPT_RCNT++) % SERIAL_VIA_INTERRUPT_RBUFLEN] = SBUF;
121 if (SERIAL_VIA_INTERRUPT_BUSY = SERIAL_VIA_INTERRUPT_XCNT) { /* Assignment, _not_ comparison! */
122 SERIAL_VIA_INTERRUPT_XCNT--;
123 SBUF = SERIAL_VIA_INTERRUPT_XBUF [SERIAL_VIA_INTERRUPT_XPOS++];
124 if (SERIAL_VIA_INTERRUPT_XPOS >= SERIAL_VIA_INTERRUPT_XBUFLEN)
125 SERIAL_VIA_INTERRUPT_XPOS = 0;
130 void putchar( char Byte )
132 while (SERIAL_VIA_INTERRUPT_XCNT >= SERIAL_VIA_INTERRUPT_XBUFLEN) /* wait for room in buffer */
138 if (SERIAL_VIA_INTERRUPT_BUSY) {
139 SERIAL_VIA_INTERRUPT_XBUF[(SERIAL_VIA_INTERRUPT_XPOS+SERIAL_VIA_INTERRUPT_XCNT++) % SERIAL_VIA_INTERRUPT_XBUFLEN] = Byte;
142 SERIAL_VIA_INTERRUPT_BUSY = 1;
147 unsigned char getchar( void )
150 while (!SERIAL_VIA_INTERRUPT_RCNT) /* wait for character */
156 SERIAL_VIA_INTERRUPT_RCNT--;
157 c = SERIAL_VIA_INTERRUPT_RBUF [SERIAL_VIA_INTERRUPT_RPOS++];
158 if (SERIAL_VIA_INTERRUPT_RPOS >= SERIAL_VIA_INTERRUPT_RBUFLEN)
159 SERIAL_VIA_INTERRUPT_RPOS = 0;
165 // ===========================================================================================
166 // Now the Internal UART Handling if Polling Method is used
167 #ifdef SERIAL_VIA_POLLING
168 void putchar( char Byte )
170 while( !TI ) /* wait for TI==1 */
179 unsigned char getchar( void )
181 while( !RI ) /* wait for RI==1 */
191 // ===========================================================================================
193 #ifdef USE_SYSTEM_TIMER
195 volatile unsigned long SystemTicks1msec;
197 // Here are the definitions of the 1kHz Timer 0
198 // used for delay( xx_msec )
200 #error "CPUCLKHZ is not defined !"
203 #define TIMER0INTSPERSECOND 1000
204 #define TIMER0MODE1RELOADVALUE (-((CPUCLKHZ/TIMER0INTSPERSECOND)/12))
206 void delayMsec( unsigned long delayTime )
208 delayTime += SystemTicks1msec;
209 while( SystemTicks1msec < delayTime )
215 void timer0_isr (void) interrupt 1
217 /* Interruptrate will be slightly slower than wanted */
218 /* because TL0 is not 0 here, not bug-fix yet */
219 TL0 = (TIMER0MODE1RELOADVALUE & 0x00FF);
220 TH0 = (TIMER0MODE1RELOADVALUE >> 8);
223 #endif // USE_SYSTEM_TIMER
225 // ===========================================================================================
226 // Global Hardware Init
227 void init_hardware( void )
229 #ifdef USE_SYSTEM_TIMER
230 SystemTicks1msec = 0x0;
231 #endif // USE_SYSTEM_TIMER
233 EA = 0; /* Disable ALL Ints */
234 ES = 0; /* Disable Serial Int */
235 ET1 = 0; /* Disable Timer 1 Int */
236 EX1 = 0; /* Disable External Interrupt 1 */
237 ET0 = 0; /* Disable Timer 0 Int */
238 EX0 = 0; /* Disable External Interrupt 0 */
240 TR1 = 0; /* Stop Timer 1 */
241 TR0 = 0; /* Stop Timer 0 */
243 #ifdef SERIAL_VIA_INTERRUPT
244 SERIAL_VIA_INTERRUPT_RCNT = SERIAL_VIA_INTERRUPT_XCNT = SERIAL_VIA_INTERRUPT_RPOS = SERIAL_VIA_INTERRUPT_XPOS = 0; /* init buffers */
245 SERIAL_VIA_INTERRUPT_BUSY = 0;
248 #ifdef SERIAL_IS_DEFINED
249 /* Init UART 9600Baud 8-Bit using Timer 1 in Mode 2*/
250 /* Set Reload Values for CPU-Clk and BaudRate */
251 TH1 = TIMER1MODE2RELOADVALUE;
252 TL1 = TIMER1MODE2RELOADVALUE;
253 TMOD &= 0x0f; /* First we set Timer 1 */
254 TMOD |= 0x20; /* Setting Timer 1 as GATE=0 TIMER and MODE 2 8-bit auto reload */
255 TR1 = 1; /* Enabling Timer 1 */
258 #ifdef USE_SYSTEM_TIMER
259 /* Init Timer 0 as Software Interrupt for 1mSec Timer */
260 TL0 = (TIMER0MODE1RELOADVALUE & 0x00FF);
261 TH0 = (TIMER0MODE1RELOADVALUE >> 8);
262 TMOD &= 0xf0; /* Now Timer 0 */
263 TMOD |= 0x01; /* Setting Timer 0 as GATE=0 TIMER and MODE 1 16-bit Timer mode */
264 TR0 = 1; /* Enabling Timer 0 */
267 #ifdef SERIAL_IS_DEFINED
268 SCON = 0x40; /* Init Serial Port as 8-Bit UART with variable Baudrate */
269 SCON |= 0x10; /* Enabling Serial reception */
270 SCON |= 0x02; /* Setting TI-Bit */
273 #ifdef USE_SYSTEM_TIMER
274 TR0 = 1; /* Start Timer 0 */
275 ET0 = 1; /* Enable Timer 0 Interrupt */
278 #ifdef SERIAL_VIA_INTERRUPT
279 ES = 1; /* Enable Serial Interrupt */
281 EA = 1; /* Enable all Enabled Interrupts */