Subversion Repositories Projects

Rev

Rev 783 | Rev 835 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
331 cascade 1
/****************************************************************************
728 cascade 2
 *   Copyright (C) 2009-2010 by Claas Anders "CaScAdE" Rathje               *
331 cascade 3
 *   admiralcascade@gmail.com                                               *
4
 *   Project-URL: http://www.mylifesucks.de/oss/c-osd/                      *
5
 *                                                                          *
6
 *   This program is free software; you can redistribute it and/or modify   *
7
 *   it under the terms of the GNU General Public License as published by   *
8
 *   the Free Software Foundation; either version 2 of the License.         *
9
 *                                                                          *
10
 *   This program is distributed in the hope that it will be useful,        *
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
13
 *   GNU General Public License for more details.                           *
14
 *                                                                          *
15
 *   You should have received a copy of the GNU General Public License      *
16
 *   along with this program; if not, write to the                          *
17
 *   Free Software Foundation, Inc.,                                        *
18
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.              *
19
 ****************************************************************************/
20
 
800 - 21
#include "main.h"
346 cascade 22
#include <avr/io.h>
23
#include <util/delay.h>
24
#include <avr/pgmspace.h> 
519 cascade 25
#include <string.h>
26
#include <stdlib.h>
331 cascade 27
#include "max7456_software_spi.h"
28
 
736 cascade 29
 
30
char conv_array[7]; // general array for number -> char conversation
31
 
800 - 32
int pow(int a, int b) {
33
    if (b <= 0) return 1;
34
    int res = 1;
35
    while (b-- > 0) res *= a;
36
    return res;
37
}
38
 
331 cascade 39
/* ##########################################################################
40
 * MAX7456 SPI & Display stuff
41
 * ##########################################################################*/
42
 
43
/**
44
 * Send a byte through SPI
519 cascade 45
 * inline because it increases the codesize currenlty 'only' by 110byte but saves
46
 * the context-change on every char and attribute which is at least done twice
47
 * (address and data byte), a significant speed-bost we do not want to miss :)
331 cascade 48
 */
519 cascade 49
inline void spi_send(uint8_t byte) {
331 cascade 50
    for (int8_t i = 7; i >= 0; i--) {
51
        if (((byte >> i) & 1)) {
52
            MAX_SDIN_HIGH
53
        } else {
54
            MAX_SDIN_LOW
55
        }
56
        MAX_SCLK_HIGH
57
        MAX_SCLK_LOW
58
    }
59
}
60
 
61
/**
62
 *  Send <byte> to <address> of MAX7456
63
 */
64
void spi_send_byte(uint8_t address, uint8_t byte) {
65
    // start sending
66
    MAX_CS_LOW
67
 
68
    spi_send(address);
69
    spi_send(byte);
70
 
71
    // end sending
72
    MAX_CS_HIGH
73
}
74
 
75
/**
76
 *  write a <character> to <address> of MAX7456 display memory
77
 */
78
void write_char(uint16_t address, char character) {
79
    spi_send_byte(0x05, (address & 0xFF00) >> 8); // DMAH
80
    spi_send_byte(0x06, (address & 0x00FF)); // DMAL
81
    spi_send_byte(0x07, character); // DMDI
82
}
83
 
84
/**
514 cascade 85
 *  clear display memory
86
 *  (also sets 8bit mode)
87
 */
88
void clear(void) {
89
    /*uint16_t memory_address = 0;
90
    for (unsigned int a = 0; a < 480; a++) {
91
        write_char(memory_address++, 0);
92
    }*/
761 - 93
    // clear all display-mem (DMM)
514 cascade 94
    spi_send_byte(0x04, 0b01000100);
95
 
96
    // clearing takes 12uS according to maxim so lets wait longer
97
    _delay_us(20);
98
}
99
 
100
 
736 cascade 101
#if (ALLCHARSDEBUG|(WRITECHARS != -1))
761 - 102
 
514 cascade 103
/**
104
 * for testing write all chars to screen
105
 */
106
void write_all_chars() {
107
    uint16_t x = 3, y = 2, t = 0;
108
    while (t < 256) {
761 - 109
        write_char(x++ + y * 30, t++);
514 cascade 110
        if (x > 25) {
111
            y++;
112
            x = 3;
113
        }
114
    }
115
}
116
 
736 cascade 117
/**
118
 * let the MAX7456 learn a new character at <number>
119
 * with <data>.
120
 */
121
void learn_char(uint8_t number, unsigned char* data) {
122
    // select character to write (CMAH)
123
    spi_send_byte(0x09, number);
124
 
125
    for (uint8_t i = 0; i < 54; i++) {
126
        // select 4pixel byte of char (CMAL)
127
        spi_send_byte(0x0A, i);
128
 
129
        // write 4pixel byte of char (CMDI)
130
        spi_send_byte(0x0B, data[i]);
131
    }
132
 
133
    // write to the NVM array from the shadow RAM (CMM)
134
    spi_send_byte(0x08, 0b10100000);
135
 
136
    // according to maxim writing to nvram takes about 12ms, lets wait longer
137
    _delay_ms(120);
138
}
139
#endif
140
 
514 cascade 141
#if !(ALLCHARSDEBUG|(WRITECHARS != -1))
142
 
143
/**
331 cascade 144
 *  write a character <attribute> to <address> of MAX7456 display memory
145
 */
146
void write_char_att(uint16_t address, char attribute) {
147
    // the only important part is that the DMAH[1] is set
148
    // so we add 2 which binary is the 2nd lowest byte
149
    spi_send_byte(0x05, ((address & 0xFF00) >> 8) | 2); // DMAH
150
    spi_send_byte(0x06, (address & 0x00FF)); // DMAL
151
    spi_send_byte(0x07, attribute); // DMDI
152
}
153
 
154
/**
155
 *  write a <character> at <x>/<y> to MAX7456 display memory
156
 */
157
void write_char_xy(uint8_t x, uint8_t y, char character) {
158
    uint16_t address = y * 30 + x;
159
    write_char(address, character);
160
}
161
 
162
/**
163
 *  write a  character <attribute> at <x>/<y> to MAX7456 display memory
164
 */
165
void write_char_att_xy(uint8_t x, uint8_t y, char attribute) {
166
    uint16_t address = y * 30 + x;
167
    write_char_att(address, attribute);
168
}
169
 
170
/**
171
 *  write an ascii <character> to <address> of MAX7456 display memory
172
 */
173
void write_ascii_char(uint16_t address, char c) {
174
    if (c == 32) c = 0; // remap space
175
    else if (c > 48 && c <= 57) c -= 48; // remap numbers
176
    else if (c == '0') c = 10; // remap zero
177
    else if (c >= 65 && c <= 90) c -= 54; // remap big letters
178
    else if (c >= 97 && c <= 122) c -= 60; // remap small letters
179
    else if (c == '(') c = 63; // remap
180
    else if (c == ')') c = 64; // remap
181
    else if (c == '.') c = 65; // remap
736 cascade 182
    else if (c == '-') c = 73; // remap minus
331 cascade 183
    else if (c == ';') c = 67; // remap
184
    else if (c == ':') c = 68; // remap
185
    else if (c == ',') c = 69; // remap
761 - 186
        //    else if (c == '?') c = 66; // remap
187
        //    else if (c == '\'') c = 70; // remap
757 cascade 188
    else if (c == '/') c = 71; // remap
761 - 189
    //    else if (c == '"') c = 72; // remap
190
    //    else if (c == '<') c = 74; // remap
191
    //    else if (c == '>') c = 75; // remap
192
    //    else if (c == '@') c = 76; // remap
331 cascade 193
    write_char(address, c);
194
}
195
 
196
/**
197
 *  write an ascii <string> at <x>/<y> to MAX7456 display memory
198
 */
199
void write_ascii_string(uint8_t x, uint8_t y, char *string) {
200
    while (*string) {
201
        write_ascii_char(((x++)+(y * 30)), *string);
202
        string++;
203
    }
204
}
205
 
206
/**
783 - 207
 *  write an ascii <string> with lenght <len> at <x>/<y> to MAX7456 display memory
208
 */
209
void write_ascii_string_len(uint8_t x, uint8_t y, char *string, uint8_t len) {
210
    while (len--) {
211
        write_ascii_char(((x++)+(y * 30)), *string);
212
        string++;
213
    }
214
}
215
 
216
/**
346 cascade 217
 *  write an ascii <string> from progmen at <x>/<y> to MAX7456 display memory
218
 */
489 woggle 219
void write_ascii_string_pgm(uint8_t x, uint8_t y, const char *string) {
761 - 220
    while (pgm_read_byte(string) != 0x00)
221
        write_ascii_char(((x++)+(y * 30)), pgm_read_byte(string++));
346 cascade 222
}
223
 
224
/**
379 cascade 225
 *  write an <string> from progmen at <x>/<y> downwards to MAX7456 display memory
226
 */
489 woggle 227
void write_string_pgm_down(uint8_t x, uint8_t y, const char *string, uint8_t length) {
761 - 228
    while (length--)
229
        write_char((x + (y++ * 30)), pgm_read_byte(string++));
379 cascade 230
}
231
 
232
/**
519 cascade 233
 * Write a unsigned <number> at <x>/<y> to MAX7456 display memory
234
 * <length> represents the length to rightbound the number
349 cascade 235
 * <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
331 cascade 236
 */
519 cascade 237
void write_ndigit_number_u(uint8_t x, uint8_t y, uint16_t number, int16_t length, uint8_t pad) {
800 - 238
    if (number >= pow(10, length)) {
239
        number = pow(10, length) - 1;
240
    }
761 - 241
    itoa(number, conv_array, 10);
242
    for (uint8_t i = 0; i < length - strlen(conv_array); i++) {
243
        if (pad) write_char((x++)+(y * 30), 10);
244
        else write_ascii_char((x++)+(y * 30), 0);
245
    }
246
    write_ascii_string(x, y, conv_array);
331 cascade 247
}
248
 
249
/**
519 cascade 250
 * Write a signed <number> at <x>/<y> to MAX7456 display memory
251
 * <length> represents the length to rightbound the number
349 cascade 252
 * <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
331 cascade 253
 */
519 cascade 254
void write_ndigit_number_s(uint8_t x, uint8_t y, int16_t number, int16_t length, uint8_t pad) {
800 - 255
    if (number <= -pow(10, length)) {
256
        number = -pow(10, length) + 1;
257
    } else if (number >= pow(10, length)) {
258
        number = pow(10, length) - 1;
259
    }
260
 
761 - 261
    itoa(number, conv_array, 10);
800 - 262
    if (strlen(conv_array) < length) {
263
        for (uint8_t i = 0; i < length - strlen(conv_array); i++) {
264
            if (pad) write_char((x++)+(y * 30), 10);
265
            else write_ascii_char((x++)+(y * 30), 0);
266
        }
761 - 267
    }
268
    write_ascii_string(x, y, conv_array);
331 cascade 269
}
270
 
271
/**
519 cascade 272
 * Write a unsigned <number> at <x>/<y> to MAX7456 display memory as /10th of value
273
 * <length> represents the length to rightbound the number
349 cascade 274
 * <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
331 cascade 275
 */
519 cascade 276
void write_ndigit_number_u_10th(uint8_t x, uint8_t y, uint16_t number, int16_t length, uint8_t pad) {
800 - 277
    if (number >= pow(10, length)) {
278
        number = pow(10, length) - 1;
279
    }
761 - 280
    itoa(number, conv_array, 10);
281
    uint8_t len = strlen(conv_array);
282
    for (uint8_t i = 0; i < length - len; i++) {
283
        if (pad) write_char((x++)+(y * 30), 10); //  zero
284
        else write_char((x++)+(y * 30), 0); // blank
285
    }
286
    char rest = conv_array[len - 1];
287
    conv_array[len - 1] = 0;
288
    if (len == 1) {
289
        write_char((x - 1)+(y * 30), 10); // zero
290
    } else if (len == 2 && conv_array[0] == '-') {
291
        write_char((x - 1)+(y * 30), 0x49); // minus
292
        write_char((x)+(y * 30), 10); // zero
293
    } else {
294
        write_ascii_string(x, y, conv_array);
295
    }
296
    x += len - 1;
297
    write_char((x++)+(y * 30), 65); // decimal point
298
    write_ascii_char((x++)+(y * 30), rest); // after dot
331 cascade 299
}
300
 
301
/**
519 cascade 302
 * Write a signed <number> at <x>/<y> to MAX7456 display memory as /10th of value
303
 * <length> represents the length to rightbound the number
349 cascade 304
 * <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
331 cascade 305
 */
519 cascade 306
void write_ndigit_number_s_10th(uint8_t x, uint8_t y, int16_t number, int16_t length, uint8_t pad) {
800 - 307
    if (number >= pow(10, length)) {
308
        number = pow(10, length) - 1;
309
    }
761 - 310
    itoa(number, conv_array, 10);
311
    uint8_t len = strlen(conv_array);
312
    for (uint8_t i = 0; i < length - len; i++) {
313
        if (pad) write_char((x++)+(y * 30), 10); //  zero
314
        else write_char((x++)+(y * 30), 0); // blank
315
    }
316
    char rest = conv_array[len - 1];
317
    conv_array[len - 1] = 0;
318
    if (len == 1) {
319
        write_char((x - 1)+(y * 30), 10); // zero
320
    } else if (len == 2 && conv_array[0] == '-') {
321
        write_char((x - 1)+(y * 30), 0x49); // minus
322
        write_char((x)+(y * 30), 10); // zero
323
    } else {
324
        write_ascii_string(x, y, conv_array);
325
    }
326
    x += len - 1;
327
    write_char((x++)+(y * 30), 65); // decimal point
328
    write_ascii_char((x++)+(y * 30), rest); // after dot
331 cascade 329
}
330
 
331
/**
332
 *  write <seconds> as human readable time at <x>/<y> to MAX7456 display mem
333
 */
334
void write_time(uint8_t x, uint8_t y, uint16_t seconds) {
335
    uint16_t min = seconds / 60;
336
    seconds -= min * 60;
519 cascade 337
    write_ndigit_number_u(x, y, min, 3, 0);
331 cascade 338
    write_char_xy(x + 3, y, 68);
519 cascade 339
    write_ndigit_number_u(x + 4, y, seconds, 2, 1);
331 cascade 340
}
341
 
342
/**
412 cascade 343
 * wirte a <position> at <x>/<y> assuming it is a gps position for long-/latitude
344
 */
345
void write_gps_pos(uint8_t x, uint8_t y, int32_t position) {
761 - 346
    if (position < 0) {
347
        position ^= ~0;
348
        position++;
349
        write_char_xy(x++, y, 0x49); // minus
350
    } else {
351
        write_char_xy(x++, y, 0); // clear ('+' would be nice, maybe later)
352
    }
353
    write_ndigit_number_u(x, y, (uint16_t)(position / (int32_t)10000000), 3, 1);
354
    write_char_xy(x + 3, y, 65); // decimal point
355
    position = position - ((position / (int32_t)10000000) * (int32_t)10000000);
356
    write_ndigit_number_u(x + 4, y, (uint16_t)(position / (int32_t)1000), 4, 1);
357
    position = position - ((uint16_t)(position / (int32_t)1000) * (int32_t)1000);
358
    write_ndigit_number_u(x + 8, y, (uint16_t)position, 3, 1);
359
    write_char_xy(x + 11, y, 0xD0); // degree symbol
412 cascade 360
}
514 cascade 361
 
362
#endif