]> git.ozlabs.org Git - minimigmac.git/blob - pic/hardware.c
Initial commit
[minimigmac.git] / pic / hardware.c
1 /*\r
2 Copyright 2005, 2006, 2007 Dennis van Weeren\r
3 \r
4 This file is part of Minimig\r
5 \r
6 Minimig is free software; you can redistribute it and/or modify\r
7 it under the terms of the GNU General Public License as published by\r
8 the Free Software Foundation; either version 3 of the License, or\r
9 (at your option) any later version.\r
10 \r
11 Minimig is distributed in the hope that it will be useful,\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 GNU General Public License for more details.\r
15 \r
16 You should have received a copy of the GNU General Public License\r
17 along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
18 \r
19 Hardware control routines\r
20 \r
21 27-11-2005      -started coding\r
22 29-01-2006      -done a lot of work\r
23 31-01-2006      -added key repeat\r
24 06-02-2006      -took out all button handling stuff\r
25 \r
26 -- Goran Ljubojevic --\r
27 2009-11-13      - OsdCommand added\r
28 2009-11-21      - small cleanup\r
29 2009-12-20      - systimer reset on every hardware init to support propper timings on reset\r
30 2009-12-30      - Support for new FPGA firmware added in header file\r
31                         - GetFPGAStatus function added\r
32 2010-01-29      - ResetFPGA() macro added to header file.\r
33 2010-08-21      - YQ100818 FPGA core support\r
34 2010-08-26      - Added firmwareConfiguration.h\r
35 2010-09-09      - Added _SPI macro to help save space on multiple SPI calls\r
36 2010-10-15      - Moved over to minimigmac, coding style changes, etc...\r
37 */\r
38 \r
39 #include <stdio.h>\r
40 \r
41 #include "hardware.h"\r
42 \r
43 static volatile unsigned short systimer;\r
44 \r
45 /*initialize hardware*/\r
46 void hardware_init(void)\r
47 {\r
48         /* Disable analog inputs */\r
49         ADCON1 = 0b00000110;\r
50 \r
51         /* Initalize output register */\r
52         PORTA = 0b00100011;\r
53         PORTB = 0b00000000;\r
54         PORTC = 0b00010001;\r
55 \r
56         /* Enable PORTB weak pullup */\r
57         INTCON2bits.RBPU = 0;\r
58 \r
59         /* Initialize SPI to master mode 0, sample on posedge, 5Mhz */\r
60         SSPSTAT = 0x40;\r
61         SSPCON1 = 0x20;\r
62 \r
63         /* Initialize input/ouput configuration */\r
64         TRISA = 0b11001100;\r
65         TRISB = 0b00101011;\r
66         TRISC = 0b10010000;\r
67 \r
68         /* Initialize serial port */\r
69         SPBRG = 10;     /*115200 BAUD @ 20MHz*/\r
70         TXSTA = 0x24;\r
71         RCSTA = 0x90;\r
72 \r
73         /* Init timer0, internal clk, prescaler 1:256 */\r
74         T0CON = 0xc7;\r
75         TMR0H = 0;\r
76         TMR0L = 0;\r
77 \r
78         /* Enable interrupt for timer 0 */\r
79         INTCONbits.TMR0IE = 1;\r
80         INTCONbits.GIE = 1;\r
81 }\r
82 \r
83 /* interrupt service routine */\r
84 static void isr(void) interrupt 1\r
85 {\r
86         unsigned short t;\r
87         static unsigned char button_state;\r
88 \r
89         /* Clear timer 0 interrupt flag */\r
90         INTCONbits.TMR0IF = 0;\r
91 \r
92         /* Set timer to timeout every 10ms\r
93          *  @20Mhz --> instruction = 200ns\r
94          *  200ns * 256 * 195  =  10ms\r
95          *\r
96          * Not sure we can just cast, so for now be gross\r
97          * since SDCC doesn't give us a 16-bit TMR0\r
98          */\r
99         t = TMR0L;\r
100         t |= ((unsigned short)TMR0H) << 8;\r
101         t -= 195;\r
102         TMR0H = t >> 8;\r
103         TMR0L = t & 0xff;\r
104 \r
105         /* Increment system timer */\r
106         systimer++;\r
107 \r
108         /* Debounce button */\r
109         if (check_button()) {\r
110                 if (button_state < 10) {\r
111                         button_state++;\r
112                         if (button_state == 10) {\r
113                                 putchar('[');\r
114                                 putchar('N');\r
115                                 putchar('M');\r
116                                 putchar('I');\r
117                                 putchar(']');\r
118                                 NMI = 1;\r
119                         }\r
120                 }\r
121         } else {\r
122                 button_state = 0;\r
123                 NMI = 0;\r
124         }\r
125 }\r
126 \r
127 /* Get system timer + offset (handy for lots of things)*/\r
128 unsigned short get_timer(unsigned short offset)\r
129 {\r
130         unsigned short r;\r
131 \r
132         /* Get system time SAFELY */\r
133         INTCONbits.GIE = 0;\r
134         r = systimer;\r
135         INTCONbits.GIE = 1;\r
136 \r
137         /*add offset*/\r
138         r += offset;\r
139 \r
140         return r;\r
141 }\r
142 \r
143 /* Check if timer is past given time in <t>\r
144  * it may be maximum 30000 ticks in the future\r
145  */\r
146 char check_timer(unsigned short t)\r
147 {\r
148         /* calculate difference */\r
149         INTCONbits.GIE = 0;\r
150         t -= systimer;\r
151         INTCONbits.GIE = 1;\r
152 \r
153         /* check if <t> has passed */\r
154         return t > 30000;\r
155 }\r
156 \r
157 void wait_timer(unsigned short time)\r
158 {\r
159     time = get_timer(time);\r
160     while (!check_timer(time))\r
161             ;\r
162 }\r
163 \r
164 /* SPI-bus. Should inline ? */\r
165 unsigned char do_spi(unsigned char d)\r
166 {\r
167         SSPBUF = d;\r
168         while (!SSPSTATbits.BF);        /*Wait untill controller is ready*/\r
169         return(SSPBUF);                 /*Return with received value*/  \r
170 }\r
171 \r
172 /* FPAG configuration serial interface */\r
173 void shift_fpga(unsigned char byte)\r
174 {\r
175         /*bit 0*/\r
176         DIN = 0;\r
177         CCLK = 0;\r
178         if (byte & 0x80)\r
179                 DIN = 1;\r
180         CCLK = 1;\r
181 \r
182         /*bit 1*/\r
183         DIN = 0;\r
184         CCLK = 0;\r
185         if (byte & 0x40)\r
186                 DIN = 1;\r
187         CCLK = 1;\r
188 \r
189         /*bit 2*/\r
190         DIN = 0;\r
191         CCLK = 0;\r
192         if (byte & 0x20)\r
193                 DIN = 1;\r
194         CCLK = 1;\r
195 \r
196         /*bit 3*/\r
197         DIN = 0;\r
198         CCLK = 0;\r
199         if (byte & 0x10)\r
200                 DIN = 1;\r
201         CCLK = 1;\r
202 \r
203         /*bit 4*/\r
204         DIN = 0;\r
205         CCLK = 0;\r
206         if (byte & 0x08)\r
207                 DIN = 1;\r
208         CCLK = 1;\r
209 \r
210         /*bit 5*/\r
211         DIN = 0;\r
212         CCLK = 0;\r
213         if (byte & 0x04)\r
214                 DIN = 1;\r
215         CCLK = 1;\r
216 \r
217         /*bit 6*/\r
218         DIN = 0;\r
219         CCLK = 0;\r
220         if (byte & 0x02)\r
221                 DIN = 1;\r
222         CCLK = 1;\r
223 \r
224         /*bit 7*/\r
225         DIN = 0;\r
226         CCLK = 0;\r
227         if (byte & 0x01)\r
228                 DIN = 1;\r
229         CCLK = 1;\r
230 }\r
231 \r
232 /* Put out a chacter to the serial port */\r
233 void putchar(char ch) __wparam\r
234 {\r
235         while(TXSTAbits.TRMT == 0);\r
236         TXREG = ch;\r
237         if (ch == 10) {\r
238                 while(TXSTAbits.TRMT == 0);\r
239                 TXREG = 13;\r
240         }\r
241 }\r
242 \r
243 \r
244 \r
245 \r
246 \r
247 \r