Subversion Repositories Projects

Rev

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

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