Subversion Repositories Projects

Rev

Rev 800 | Rev 902 | 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
835 - 186
    else if (c == '?') c = 66; // remap
187
    else if (c == '\\') c = 70; // remap
188
    else if (c == '_') c = 0xE3; // remap
757 cascade 189
    else if (c == '/') c = 71; // remap
835 - 190
    else if (c == '"') c = 72; // remap
191
    else if (c == '<') c = 74; // remap
192
    else if (c == '>') c = 75; // remap
193
    else if (c == '@') c = 76; // remap
331 cascade 194
    write_char(address, c);
195
}
196
 
197
/**
198
 *  write an ascii <string> at <x>/<y> to MAX7456 display memory
199
 */
200
void write_ascii_string(uint8_t x, uint8_t y, char *string) {
201
    while (*string) {
202
        write_ascii_char(((x++)+(y * 30)), *string);
203
        string++;
204
    }
205
}
206
 
207
/**
783 - 208
 *  write an ascii <string> with lenght <len> at <x>/<y> to MAX7456 display memory
209
 */
210
void write_ascii_string_len(uint8_t x, uint8_t y, char *string, uint8_t len) {
211
    while (len--) {
212
        write_ascii_char(((x++)+(y * 30)), *string);
213
        string++;
214
    }
215
}
216
 
217
/**
346 cascade 218
 *  write an ascii <string> from progmen at <x>/<y> to MAX7456 display memory
219
 */
489 woggle 220
void write_ascii_string_pgm(uint8_t x, uint8_t y, const char *string) {
761 - 221
    while (pgm_read_byte(string) != 0x00)
222
        write_ascii_char(((x++)+(y * 30)), pgm_read_byte(string++));
346 cascade 223
}
224
 
225
/**
379 cascade 226
 *  write an <string> from progmen at <x>/<y> downwards to MAX7456 display memory
227
 */
489 woggle 228
void write_string_pgm_down(uint8_t x, uint8_t y, const char *string, uint8_t length) {
761 - 229
    while (length--)
230
        write_char((x + (y++ * 30)), pgm_read_byte(string++));
379 cascade 231
}
232
 
233
/**
519 cascade 234
 * Write a unsigned <number> at <x>/<y> to MAX7456 display memory
235
 * <length> represents the length to rightbound the number
349 cascade 236
 * <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
331 cascade 237
 */
519 cascade 238
void write_ndigit_number_u(uint8_t x, uint8_t y, uint16_t number, int16_t length, uint8_t pad) {
800 - 239
    if (number >= pow(10, length)) {
240
        number = pow(10, length) - 1;
241
    }
761 - 242
    itoa(number, conv_array, 10);
243
    for (uint8_t i = 0; i < length - strlen(conv_array); i++) {
244
        if (pad) write_char((x++)+(y * 30), 10);
245
        else write_ascii_char((x++)+(y * 30), 0);
246
    }
247
    write_ascii_string(x, y, conv_array);
331 cascade 248
}
249
 
250
/**
519 cascade 251
 * Write a signed <number> at <x>/<y> to MAX7456 display memory
252
 * <length> represents the length to rightbound the number
349 cascade 253
 * <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
331 cascade 254
 */
519 cascade 255
void write_ndigit_number_s(uint8_t x, uint8_t y, int16_t number, int16_t length, uint8_t pad) {
800 - 256
    if (number <= -pow(10, length)) {
257
        number = -pow(10, length) + 1;
258
    } else if (number >= pow(10, length)) {
259
        number = pow(10, length) - 1;
260
    }
261
 
761 - 262
    itoa(number, conv_array, 10);
800 - 263
    if (strlen(conv_array) < length) {
264
        for (uint8_t i = 0; i < length - strlen(conv_array); i++) {
265
            if (pad) write_char((x++)+(y * 30), 10);
266
            else write_ascii_char((x++)+(y * 30), 0);
267
        }
761 - 268
    }
269
    write_ascii_string(x, y, conv_array);
331 cascade 270
}
271
 
272
/**
519 cascade 273
 * Write a unsigned <number> at <x>/<y> to MAX7456 display memory as /10th of value
274
 * <length> represents the length to rightbound the number
349 cascade 275
 * <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
331 cascade 276
 */
519 cascade 277
void write_ndigit_number_u_10th(uint8_t x, uint8_t y, uint16_t number, int16_t length, uint8_t pad) {
800 - 278
    if (number >= pow(10, length)) {
279
        number = pow(10, length) - 1;
280
    }
761 - 281
    itoa(number, conv_array, 10);
282
    uint8_t len = strlen(conv_array);
283
    for (uint8_t i = 0; i < length - len; i++) {
284
        if (pad) write_char((x++)+(y * 30), 10); //  zero
285
        else write_char((x++)+(y * 30), 0); // blank
286
    }
287
    char rest = conv_array[len - 1];
288
    conv_array[len - 1] = 0;
289
    if (len == 1) {
290
        write_char((x - 1)+(y * 30), 10); // zero
291
    } else if (len == 2 && conv_array[0] == '-') {
292
        write_char((x - 1)+(y * 30), 0x49); // minus
293
        write_char((x)+(y * 30), 10); // zero
294
    } else {
295
        write_ascii_string(x, y, conv_array);
296
    }
297
    x += len - 1;
298
    write_char((x++)+(y * 30), 65); // decimal point
299
    write_ascii_char((x++)+(y * 30), rest); // after dot
331 cascade 300
}
301
 
302
/**
519 cascade 303
 * Write a signed <number> at <x>/<y> to MAX7456 display memory as /10th of value
304
 * <length> represents the length to rightbound the number
349 cascade 305
 * <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of   7
331 cascade 306
 */
519 cascade 307
void write_ndigit_number_s_10th(uint8_t x, uint8_t y, int16_t number, int16_t length, uint8_t pad) {
800 - 308
    if (number >= pow(10, length)) {
309
        number = pow(10, length) - 1;
310
    }
761 - 311
    itoa(number, conv_array, 10);
312
    uint8_t len = strlen(conv_array);
313
    for (uint8_t i = 0; i < length - len; i++) {
314
        if (pad) write_char((x++)+(y * 30), 10); //  zero
315
        else write_char((x++)+(y * 30), 0); // blank
316
    }
317
    char rest = conv_array[len - 1];
318
    conv_array[len - 1] = 0;
319
    if (len == 1) {
320
        write_char((x - 1)+(y * 30), 10); // zero
321
    } else if (len == 2 && conv_array[0] == '-') {
322
        write_char((x - 1)+(y * 30), 0x49); // minus
323
        write_char((x)+(y * 30), 10); // zero
324
    } else {
325
        write_ascii_string(x, y, conv_array);
326
    }
327
    x += len - 1;
328
    write_char((x++)+(y * 30), 65); // decimal point
329
    write_ascii_char((x++)+(y * 30), rest); // after dot
331 cascade 330
}
331
 
332
/**
333
 *  write <seconds> as human readable time at <x>/<y> to MAX7456 display mem
334
 */
335
void write_time(uint8_t x, uint8_t y, uint16_t seconds) {
336
    uint16_t min = seconds / 60;
337
    seconds -= min * 60;
519 cascade 338
    write_ndigit_number_u(x, y, min, 3, 0);
331 cascade 339
    write_char_xy(x + 3, y, 68);
519 cascade 340
    write_ndigit_number_u(x + 4, y, seconds, 2, 1);
331 cascade 341
}
342
 
343
/**
412 cascade 344
 * wirte a <position> at <x>/<y> assuming it is a gps position for long-/latitude
345
 */
346
void write_gps_pos(uint8_t x, uint8_t y, int32_t position) {
761 - 347
    if (position < 0) {
348
        position ^= ~0;
349
        position++;
350
        write_char_xy(x++, y, 0x49); // minus
351
    } else {
352
        write_char_xy(x++, y, 0); // clear ('+' would be nice, maybe later)
353
    }
354
    write_ndigit_number_u(x, y, (uint16_t)(position / (int32_t)10000000), 3, 1);
355
    write_char_xy(x + 3, y, 65); // decimal point
356
    position = position - ((position / (int32_t)10000000) * (int32_t)10000000);
357
    write_ndigit_number_u(x + 4, y, (uint16_t)(position / (int32_t)1000), 4, 1);
358
    position = position - ((uint16_t)(position / (int32_t)1000) * (int32_t)1000);
359
    write_ndigit_number_u(x + 8, y, (uint16_t)position, 3, 1);
360
    write_char_xy(x + 11, y, 0xD0); // degree symbol
412 cascade 361
}
514 cascade 362
 
363
#endif