-
Notifications
You must be signed in to change notification settings - Fork 0
/
mipslabfunc.c
executable file
·256 lines (215 loc) · 7.37 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
// Everything from here until otherwise stated is premade from labs
/* mipslabfunc.c
This file written 2015 by F Lundevall
Some parts are original code written by Axel Isaksson
This file modified 2023-03-01 by Theodor Björkman
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--);
}
/* tick:
Add 1 to time in memory, at location pointed to by parameter.
Time is stored as 4 pairs of 2 NBCD-digits.
1st pair (most significant byte) counts days.
2nd pair counts hours.
3rd pair counts minutes.
4th pair (least significant byte) counts seconds.
In most labs, only the 3rd and 4th pairs are used. */
void tick( unsigned int * timep )
{
/* Get current value, store locally */
register unsigned int t = * timep;
t += 1; /* Increment local copy */
/* If result was not a valid BCD-coded time, adjust now */
if( (t & 0x0000000f) >= 0x0000000a ) t += 0x00000006;
if( (t & 0x000000f0) >= 0x00000060 ) t += 0x000000a0;
/* Seconds are now OK */
if( (t & 0x00000f00) >= 0x00000a00 ) t += 0x00000600;
if( (t & 0x0000f000) >= 0x00006000 ) t += 0x0000a000;
/* Minutes are now OK */
if( (t & 0x000f0000) >= 0x000a0000 ) t += 0x00060000;
if( (t & 0x00ff0000) >= 0x00240000 ) t += 0x00dc0000;
/* Hours are now OK */
if( (t & 0x0f000000) >= 0x0a000000 ) t += 0x06000000;
if( (t & 0xf0000000) >= 0xa0000000 ) t = 0;
/* Days are now OK */
* timep = t; /* Store new value */
}
uint8_t spi_send_recv(uint8_t data) {
while(!(SPI2STAT & 0x08));
SPI2BUF = data;
while(!(SPI2STAT & 1));
return SPI2BUF;
}
void display_init(void) {
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_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]);
}
}
}
/*
* 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 ] );
}
// Code below is written by Theodor Björkman
#define ssr(n) (spi_send_recv(n))
void display_scene(uint8_t *data) {
//
DISPLAY_CHANGE_TO_COMMAND_MODE; // Settings för hur vi ska inputta skiten
ssr(0x20); // 0010 0000 set memory addressing mode, borde vara horizontal
ssr(0); // möjligtvis krävs
ssr(0xa6); // set display to normal (a7 is inverse)
ssr(0x21); // 0x21 set column address
ssr(0); // column start
ssr(127); // end address
ssr(0x22); // set page address
ssr(0); // start
ssr(3); // end
DISPLAY_CHANGE_TO_DATA_MODE;
int i;
for (i = 0; i < 512; i++)
{
ssr(data[i]);
}
}