-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmipslabfunc.c
291 lines (243 loc) · 7.39 KB
/
mipslabfunc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
/* mipslabfunc.c
This file written 2015 by F Lundevall
Some parts are original code written by Axel Isaksson
For copyright and licensing, see file COPYING */
#include <stdint.h> /* Declarations of uint_32 and the like */
#include <pic32mx.h> /* Declarations of system-specific addresses etc */
#include "mipslab.h" /* Declatations for these labs */
/* Declare a helper function which is local to this file */
static void num32asc( char * s, int );
#define DISPLAY_CHANGE_TO_COMMAND_MODE (PORTFCLR = 0x10)
#define DISPLAY_CHANGE_TO_DATA_MODE (PORTFSET = 0x10)
#define DISPLAY_ACTIVATE_RESET (PORTGCLR = 0x200)
#define DISPLAY_DO_NOT_RESET (PORTGSET = 0x200)
#define DISPLAY_ACTIVATE_VDD (PORTFCLR = 0x40)
#define DISPLAY_ACTIVATE_VBAT (PORTFCLR = 0x20)
#define DISPLAY_TURN_OFF_VDD (PORTFSET = 0x40)
#define DISPLAY_TURN_OFF_VBAT (PORTFSET = 0x20)
/* quicksleep:
A simple function to create a small delay.
Very inefficient use of computing resources,
but very handy in some special cases. */
void quicksleep(int cyc) {
int i;
for(i = cyc; i > 0; i--);
}
/* display_debug
A function to help debugging.
After calling display_debug,
the two middle lines of the display show
an address and its current contents.
There's one parameter: the address to read and display.
Note: When you use this function, you should comment out any
repeated calls to display_image; display_image overwrites
about half of the digits shown by display_debug.
*/
void display_debug( volatile int * const addr )
{
display_string( 1, "Addr" );
display_string( 2, "Data" );
num32asc( &textbuffer[1][6], (int) addr );
num32asc( &textbuffer[2][6], *addr );
display_update();
}
/* added by Ludvig Christensen & Martin Falke */
void display_rgb(volatile int * const red, volatile int * const green, volatile int * const blue){
display_string( 1, "R" );
display_string( 2, "G" );
display_string( 3, "B" );
num32asc(&textbuffer[1][6], *red);
num32asc(&textbuffer[2][6], *green);
num32asc(&textbuffer[3][6], *blue);
display_update();
}
uint8_t spi_send_recv(uint8_t data) {
while(!(SPI2STAT & 0x08));
SPI2BUF = data;
while(!(SPI2STAT & 1));
return SPI2BUF;
}
void display_init(void) {
/* Set up peripheral bus clock */
OSCCON &= ~0x180000;
OSCCON |= 0x080000;
/* Set up output pins */
AD1PCFG = 0xFFFF;
ODCE = 0x0;
TRISECLR = 0xFF;
PORTE = 0x0;
/* Output pins for display signals */
PORTF = 0xFFFF;
PORTG = (1 << 9);
ODCF = 0x0;
ODCG = 0x0;
TRISFCLR = 0x70;
TRISGCLR = 0x200;
/* Set up input pins */
TRISDSET = (1 << 8);
TRISFSET = (1 << 1);
/* Set up SPI as master */
SPI2CON = 0;
SPI2BRG = 4;
/* Clear SPIROV*/
SPI2STATCLR &= ~0x40;
/* Set CKP = 1, MSTEN = 1; */
SPI2CON |= 0x60;
/* Turn on SPI */
SPI2CONSET = 0x8000;
/* Set up input pins */
TRISDSET = (1 << 8);
TRISFSET = (1 << 1);
DISPLAY_CHANGE_TO_COMMAND_MODE;
quicksleep(10);
DISPLAY_ACTIVATE_VDD;
quicksleep(1000000);
spi_send_recv(0xAE);
DISPLAY_ACTIVATE_RESET;
quicksleep(10);
DISPLAY_DO_NOT_RESET;
quicksleep(10);
spi_send_recv(0x8D);
spi_send_recv(0x14);
spi_send_recv(0xD9);
spi_send_recv(0xF1);
DISPLAY_ACTIVATE_VBAT;
quicksleep(10000000);
spi_send_recv(0xA1);
spi_send_recv(0xC8);
spi_send_recv(0xDA);
spi_send_recv(0x20);
spi_send_recv(0xAF);
}
void display_string(int line, char *s) {
int i;
if(line < 0 || line >= 4)
return;
if(!s)
return;
for(i = 0; i < 16; i++)
if(*s) {
textbuffer[line][i] = *s;
s++;
} else
textbuffer[line][i] = ' ';
}
void display_image(int x, const uint8_t *data) {
int i, j;
for(i = 0; i < 4; i++) {
DISPLAY_CHANGE_TO_COMMAND_MODE;
spi_send_recv(0x22);
spi_send_recv(i);
spi_send_recv(x & 0xF);
spi_send_recv(0x10 | ((x >> 4) & 0xF));
DISPLAY_CHANGE_TO_DATA_MODE;
for(j = 0; j < 32; j++)
spi_send_recv(~data[i*32 + j]);
}
}
void display_update(void) {
int i, j, k;
int c;
for(i = 0; i < 4; i++) {
DISPLAY_CHANGE_TO_COMMAND_MODE;
spi_send_recv(0x22);
spi_send_recv(i);
spi_send_recv(0x0);
spi_send_recv(0x10);
DISPLAY_CHANGE_TO_DATA_MODE;
for(j = 0; j < 16; j++) {
c = textbuffer[i][j];
if(c & 0x80)
continue;
for(k = 0; k < 8; k++)
spi_send_recv(font[c*8 + k]);
}
}
}
/* Helper function, local to this file.
Converts a number to hexadecimal ASCII digits. */
void num32asc( char * s, int n )
{
int i;
for( i = 28; i >= 0; i -= 4 )
*s++ = "0123456789ABCDEF"[ (n >> i) & 15 ];
}
/*
* itoa
*
* Simple conversion routine
* Converts binary to decimal numbers
* Returns pointer to (static) char array
*
* The integer argument is converted to a string
* of digits representing the integer in decimal format.
* The integer is considered signed, and a minus-sign
* precedes the string of digits if the number is
* negative.
*
* This routine will return a varying number of digits, from
* one digit (for integers in the range 0 through 9) and up to
* 10 digits and a leading minus-sign (for the largest negative
* 32-bit integers).
*
* If the integer has the special value
* 100000...0 (that's 31 zeros), the number cannot be
* negated. We check for this, and treat this as a special case.
* If the integer has any other value, the sign is saved separately.
*
* If the integer is negative, it is then converted to
* its positive counterpart. We then use the positive
* absolute value for conversion.
*
* Conversion produces the least-significant digits first,
* which is the reverse of the order in which we wish to
* print the digits. We therefore store all digits in a buffer,
* in ASCII form.
*
* To avoid a separate step for reversing the contents of the buffer,
* the buffer is initialized with an end-of-string marker at the
* very end of the buffer. The digits produced by conversion are then
* stored right-to-left in the buffer: starting with the position
* immediately before the end-of-string marker and proceeding towards
* the beginning of the buffer.
*
* For this to work, the buffer size must of course be big enough
* to hold the decimal representation of the largest possible integer,
* and the minus sign, and the trailing end-of-string marker.
* The value 24 for ITOA_BUFSIZ was selected to allow conversion of
* 64-bit quantities; however, the size of an int on your current compiler
* may not allow this straight away.
*/
#define ITOA_BUFSIZ ( 24 )
char * itoaconv( int num )
{
register int i, sign;
static char itoa_buffer[ ITOA_BUFSIZ ];
static const char maxneg[] = "-2147483648";
itoa_buffer[ ITOA_BUFSIZ - 1 ] = 0; /* Insert the end-of-string marker. */
sign = num; /* Save sign. */
if( num < 0 && num - 1 > 0 ) /* Check for most negative integer */
{
for( i = 0; i < sizeof( maxneg ); i += 1 )
itoa_buffer[ i + 1 ] = maxneg[ i ];
i = 0;
}
else
{
if( num < 0 ) num = -num; /* Make number positive. */
i = ITOA_BUFSIZ - 2; /* Location for first ASCII digit. */
do {
itoa_buffer[ i ] = num % 10 + '0';/* Insert next digit. */
num = num / 10; /* Remove digit from number. */
i -= 1; /* Move index to next empty position. */
} while( num > 0 );
if( sign < 0 )
{
itoa_buffer[ i ] = '-';
i -= 1;
}
}
/* Since the loop always sets the index i to the next empty position,
* we must add 1 in order to return a pointer to the first occupied position. */
return( &itoa_buffer[ i + 1 ] );
}