Forum: Mikrocontroller und Digitale Elektronik LED Matrix 5x7 programm


von Markus (Gast)


Lesenswert?

So leute würde meiner freundin das hier gerne schenken 
:http://tinkerlog.com/howto/64pixels/

hab leider nur ein 5x7 led matrix. Wie stell ich das nun an an, das 
programm umzuschreiben? Wäre euch sehr dankbar, da ich es meiner 
Freundin nachträglich zum Valentienstag schenken will.
Hab das Programm von dieser seite ein bisschen gekürzt. ist das so 
korrekt?
lg


/* 
-----------------------------------------------------------------------
 * Title:    8x8 LED dot matrix animations
 * Author:   Alexander Weber alex@tinkerlog.com
 * Date:     21.12.2008
 * Hardware: ATtiny2313V
 * Software: AVRMacPack
 *
 */
1
#include <avr/io.h>
2
#include <avr/pgmspace.h>
3
4
#ifndef FONT_H_
5
#define FONT_H_
6
7
#define MAX_CHARS 59
8
#define CHAR_OFFSET 0x20
9
10
const uint8_t font[] PROGMEM = {
11
  // 3 chars bitmap, 1 char length
12
   0x00, 0x00, 0x00, 0x01 ,    // 0x20, 32, ' '  
13
   0x17, 0x00, 0x00, 0x01 ,    // 0x21, 33, !  
14
   0x03, 0x00, 0x03, 0x03 ,    // 0x22, 34, "  
15
   0x00, 0x00, 0x00, 0x03 ,    // 0x23, 35, #  
16
   0x00, 0x00, 0x00, 0x03 ,    // 0x24, 36, $  
17
   0x00, 0x00, 0x00, 0x03 ,    // 0x25, 37, %  
18
   0x00, 0x00, 0x00, 0x03 ,    // 0x26, 38, &  
19
   0x03, 0x00, 0x00, 0x01 ,    // 0x27, 39, '  
20
   0x0e, 0x11, 0x00, 0x02 ,    // 0x28, 40, (  
21
   0x11, 0x0e, 0x00, 0x02 ,    // 0x29, 41, )  
22
   0x00, 0x00, 0x00, 0x03 ,    // 0x2A, 42, *  
23
   0x08, 0x1c, 0x08, 0x03 ,    // 0x2B, 43, +  
24
   0x18, 0x00, 0x00, 0x01 ,    // 0x2C, 44, ,  
25
   0x04, 0x04, 0x00, 0x03 ,    // 0x2D, 45, -  
26
   0x10, 0x00, 0x00, 0x01 ,    // 0x2E, 46, .  
27
   0x18, 0x04, 0x03, 0x03 ,    // 0x2F, 47, /  
28
   0x1f, 0x11, 0x1f, 0x03 ,    // 0x30, 48, 0
29
   0x01, 0x1f, 0x00, 0x02 ,    // 0x31, 49, 1
30
   0x1d, 0x15, 0x17, 0x03 ,    // 0x32, 50, 2
31
   0x15, 0x15, 0x0e, 0x03 ,    // 0x33, 51, 3
32
   0x0f, 0x08, 0x1f, 0x03 ,    // 0x34, 52, 4
33
   0x17, 0x15, 0x1d, 0x03 ,    // 0x35, 53, 5
34
   0x1f, 0x12, 0x1e, 0x03 ,    // 0x36, 54, 6
35
   0x11, 0x09, 0x07, 0x03 ,    // 0x37, 55, 7
36
   0x1f, 0x15, 0x1f, 0x03 ,    // 0x38, 56, 8
37
   0x0f, 0x09, 0x1f, 0x03 ,    // 0x39, 57, 9  
38
   0x0a, 0x00, 0x00, 0x01 ,    // 0x3A, 58, :
39
   0x1a, 0x00, 0x00, 0x01 ,    // 0x3B, 59, ;  
40
   0x08, 0x14, 0x00, 0x02 ,    // 0x3C, 60, <  
41
   0x14, 0x14, 0x00, 0x02 ,    // 0x3D, 61, =  
42
   0x14, 0x08, 0x00, 0x02 ,    // 0x3E, 62, >  
43
   0x15, 0x05, 0x02, 0x03 ,    // 0x3F, 63, ?  
44
   0x0e, 0x17, 0x16, 0x03 ,    // 0x40, 64, @  
45
   0x1f, 0x09, 0x1e, 0x03 ,    // 0x41, 65, A
46
   0x1f, 0x15, 0x0a, 0x03 ,    // 0x42, 66, B
47
   0x0e, 0x11, 0x11, 0x03 ,    // 0x43, 67, C
48
   0x1f, 0x11, 0x0e, 0x03 ,    // 0x44, 68, D
49
   0x0e, 0x15, 0x15, 0x03 ,    // 0x45, 69, E
50
   0x1e, 0x05, 0x05, 0x03 ,    // 0x46, 70, F
51
   0x0e, 0x11, 0x1d, 0x03 ,    // 0x47, 71, G
52
   0x1f, 0x04, 0x1f, 0x03 ,    // 0x48, 72, H
53
   0x1f, 0x00, 0x00, 0x01 ,    // 0x49, 73, I
54
   0x08, 0x10, 0x0f, 0x03 ,    // 0x4A, 74, J
55
   0x1f, 0x04, 0x1b, 0x03 ,    // 0x4B, 75, K
56
   0x0f, 0x10, 0x10, 0x03 ,    // 0x4C, 76, L
57
   0x1f, 0x02, 0x1f, 0x03 ,    // 0x4D, 77, M
58
   0x1f, 0x01, 0x1e, 0x03 ,    // 0x4E, 78, N
59
   0x0e, 0x11, 0x0e, 0x03 ,    // 0x4F, 79, O
60
   0x1f, 0x09, 0x06, 0x03 ,    // 0x50, 80, P
61
   0x06, 0x19, 0x06, 0x03 ,    // 0x51, 81, Q
62
   0x1f, 0x09, 0x16, 0x03 ,    // 0x52, 82, R
63
   0x12, 0x15, 0x09, 0x03 ,    // 0x53, 83, S
64
   0x01, 0x1f, 0x01, 0x03 ,    // 0x54, 84, T
65
   0x0f, 0x10, 0x0f, 0x03 ,    // 0x55, 85, U
66
   0x1f, 0x10, 0x0f, 0x03 ,    // 0x56, 86, V
67
   0x1f, 0x08, 0x1f, 0x03 ,    // 0x57, 87, W
68
   0x1b, 0x04, 0x1b, 0x03 ,    // 0x58, 88, X
69
   0x03, 0x1c, 0x03, 0x03 ,    // 0x59, 89, Y
70
   0x19, 0x15, 0x13, 0x03 ,    // 0x5A, 90, Z
71
   0x1f, 0x11, 0x00, 0x02 ,    // 0x5B, 91, [
72
   0x03, 0x04, 0x18, 0x03 ,    // 0x5C, 92, 
73
   0x11, 0x1f, 0x00, 0x02 ,    // 0x5D, 93, [
74
   0x11, 0x1f, 0x00, 0x02 ,    // 0x5E, 94, ^
75
   0x1f, 0x1f, 0x1f, 0x03     // 0x5F, 95, _, used as block, all on
76
};
77
78
/* -----------------------------------------------------------------------
79
 * Title:    8x8 LED dot matrix animations
80
 * Author:   Alexander Weber alex@tinkerlog.com
81
 * Date:     21.12.2008
82
 * Hardware: ATtiny2313V
83
 * Software: AVRMacPack
84
 * 
85
 */
86
87
#include <inttypes.h>
88
#include <stdlib.h>
89
#include <string.h>
90
#include <avr/io.h>
91
#include <avr/interrupt.h>
92
#include <avr/eeprom.h>
93
#include <util/delay.h>
94
#include <avr/pgmspace.h>
95
#include "font.h"
96
97
// Change these values to adjust scroll speeds and animation iterations
98
#define ANIMATION_SCROLL_SPEED 80  // how fast to scroll the animations
99
#define TEXT_SCROLL_SPEED 120      // how fast to scrill the text
100
#define REPEAT_ANIMATION 10        // how often to repeat the animation if in cycling mode
101
#define REPEAT_TEXT 5              // how often to repeat the text if in cycling mode
102
#define F_CPU
103
// How to add a new message:
104
// * add the new message (only upper case, see font.h)
105
// * adjust MAX_MESSAGES
106
// * add the new message to messages
107
// NOTE: messages may not be longer than 59 chars. Otherwise they will not fit in the buffer.
108
//                                              123456789012345678901234567890123456789012345678901234567890
109
const prog_char PROGMEM message_00[] PROGMEM = "   WTF!?! ";
110
const prog_char PROGMEM message_01[] PROGMEM = "   I AM NO BOMB! ";
111
const prog_char PROGMEM message_02[] PROGMEM = "   5   4   3   2   1  ...  BOOM! ";
112
const prog_char PROGMEM message_03[] PROGMEM = "   I'M SORRY DAVE, I'M AFRAID I CAN'T DO THAT.  ";
113
const prog_char PROGMEM message_04[] PROGMEM = "   NOW BYE ME A SOLDERING STATION ";
114
const prog_char PROGMEM message_05[] PROGMEM = "   MAKE STUFF ";
115
const prog_char PROGMEM message_06[] PROGMEM = "   IF YOU CAN'T OPEN IT, YOU DON'T OWN IT ";
116
const prog_char PROGMEM message_07[] PROGMEM = "   1337 3L3X7RON!C5 !1!! ";
117
const prog_char PROGMEM message_08[] PROGMEM = "   MY KUNG FU IS BETTER THAN YOURS ";
118
const prog_char PROGMEM message_09[] PROGMEM = "   SUDO MAKE ME A SANDWICH ";
119
const prog_char PROGMEM message_10[] PROGMEM = "   ZOMBIES AHEAD ";
120
const prog_char PROGMEM message_11[] PROGMEM = "   HTTP://TINKERLOG.COM ";
121
122
#define MAX_MESSAGES 12
123
PGM_P PROGMEM messages[] = {
124
  message_00
125
  ,message_01
126
  ,message_02
127
  ,message_03
128
  ,message_04
129
  ,message_05
130
  ,message_06
131
  ,message_07
132
  ,message_08
133
  ,message_09
134
  ,message_10
135
  ,message_11
136
}; 
137
138
#define MAX_ANIMATIONS 3
139
const prog_uint8_t PROGMEM sprite_00[] = 
140
  {
141
    0x18,    // ___XX___
142
    0x3C,    // __XXXX__
143
    0x7E,    // _XXXXXX_
144
    0xDB,    // X_XXXX_X
145
    0xFF,    // XXXXXXXX
146
    0x24,    // __X__X__
147
    0x5A,    // _X_XX_X_
148
    0xA5     // X_X__X_X
149
  };
150
151
const prog_uint8_t PROGMEM sprite_01[8] =
152
  {
153
    0x18,    // ___XX___ 
154
    0x3C,    // __XXXX__
155
    0x7E,    // _XXXXXX_
156
    0xDB,    // X_XXXX_X
157
    0xFF,    // XXXXXXXX
158
    0x24,    // __X__X__
159
    0x42,    // _X____X_
160
    0x24     // __X__X__
161
  };
162
const prog_uint8_t PROGMEM sprite_02[8] =
163
  {
164
    0x00,    // ________ 
165
    0x00,    // ________
166
    0x14,    // ___X_X__
167
    0x3E,    // __XXXXX_
168
    0x3E,    // __XXXXX_
169
    0x1C,    // ___XXX__
170
    0x08,    // ____X___
171
    0x00     // ________
172
  };
173
174
const prog_uint8_t PROGMEM sprite_03[8] =
175
  {
176
    0x00,    // ________ 
177
    0x66,    // _XX__XX_
178
    0xFF,    // XXXXXXXX
179
    0xFF,    // XXXXXXXX
180
    0xFF,    // XXXXXXXX
181
    0x7E,    // _XXXXXX_
182
    0x3C,    // __XXXX__
183
    0x18     // ___XX___
184
  };
185
186
const prog_uint8_t PROGMEM sprite_04[8] =
187
  {
188
    0x24,    // __X__X__
189
    0x7E,    // _XXXXXX_
190
    0xDB,    // XX_XX_XX
191
    0xFF,    // XXXXXXXX
192
    0xA5,    // X_X__X_X
193
    0x99,    // X__XX__X
194
    0x81,    // X______X
195
    0xC3     // XX____XX
196
  };
197
198
const prog_uint8_t PROGMEM sprite_05[8] =
199
  {
200
    0x24,    // __X__X__
201
    0x18,    // ___XX___
202
    0x7E,    // X_XXXX_X
203
    0xDB,    // XX_XX_XX
204
    0xFF,    // XXXXXXXX
205
    0xDB,    // X_XXXX_X
206
    0x99,    // X__XX__X
207
    0xC3     // XX____XX
208
  };
209
210
211
212
uint8_t mode_ee EEMEM = 0;                      // stores the mode in eeprom
213
static uint8_t screen_mem[8];      // screen memory
214
static uint8_t active_row;      // active row
215
static uint8_t buffer[60];                      // stores the active message or sprite
216
static uint8_t message_ptr = 0;                 // points to the active char in the message
217
static uint8_t message_displayed = 0;           // how often has the message been displayed?
218
static uint8_t active_char = 0;                 // stores the active char
219
static uint8_t message_length = 0;              // stores the length of the active message
220
static uint8_t char_ptr = 0;                    // points to the active col in the char
221
static uint8_t char_length = 0;                 // stores the length of the active char
222
static volatile uint16_t counter = 0;           // used for delay function
223
224
// prototypes
225
void delay_ms(uint16_t delay);
226
void copy_to_display(int8_t x, int8_t y, uint8_t sprite[]);
227
void display_active_row(void);
228
void show_char();
229
void clear_screen(void);
230
void copy_to_buffer(const prog_uint8_t sprite[8]);
231
void scroll_animation(const prog_uint8_t sprite_1[], const prog_uint8_t sprite_2[]);
232
233
234
235
/*
236
 * ISR TIMER0_OVF_vect
237
 * Handles overflow interrupts of timer 0.
238
 *
239
 * 4MHz
240
 * ----
241
 * Prescaler 8 ==> 1953.1 Hz
242
 * Complete display = 244 Hz
243
 *
244
 */
245
ISR(TIMER0_OVF_vect) {  
246
  display_active_row();
247
  counter++;
248
}
249
250
251
252
/*
253
 * delay_ms
254
 * Uses the counter that is incremented by the ISR.
255
 * Max delay is 32767ms.
256
 */
257
void delay_ms(uint16_t delay) {
258
  while (!(PIND & (1 << PD6))) {}   // used to stop the animation when PD6 goes LOW
259
  uint16_t t = delay * 2;
260
  counter = 0;
261
  while (counter < t) {}
262
}
263
264
265
266
/*
267
 * copy_to_display
268
 * Copies sprite data to the screen memory at the given position. 
269
 */
270
void copy_to_display(int8_t x, int8_t y, uint8_t sprite[8]) {
271
  int8_t i, t;
272
  uint8_t row;
273
  for (i = 0; i < 8; i++) {
274
    t = i-y;
275
    row = ((t >= 0) && (t < 8)) ? sprite[t] : 0x00;
276
    row = (x >= 0) ? (row >> x) : (row << -x);
277
    screen_mem[i] = row;
278
  }
279
}
280
281
282
283
/*
284
 * display_active_col
285
 * Deactivates the active column and displays the next one.
286
 * Data is read from screen_mem.
287
 *
288
 *      ATtiny2313
289
 * 16 - PD0    PB7 - 1
290
 * 15 - PD1    PB6 - 2
291
 * 14 - PA1    PB5 - 3
292
 * 13 - PA0    PB4 - 4
293
 * 12 - PD2    PB3 - 5
294
 * 11 - PD3    PB2 - 6
295
 * 10 - PD4    PB1 - 7
296
 *  9 - PD5    PB0 - 8
297
 *
298
 * NFM-12883 common anode          |
299
 *     A0B5B4D4B2D3D1D0      +-----+
300
 * PD5 o o o o o o o o       |     |
301
 * PA1 o o o o o o o o      _+_    |
302
 * PB0 o o o o o o o o      \ /    |
303
 * PD2 o o o o o o o o     __V__   |
304
 * PB7 o o o o o o o o       |     |
305
 * PB1 o o o o o o o o    ---+-----C---
306
 * PB6 o o o o o o o o             |
307
 * PB3 o o o o o o o o
308
 *
309
 */
310
void display_active_row(void) {
311
312
  uint8_t row;
313
314
  // shut down all rows and columns
315
  PORTA = (0 << PA0) | (1 << PA1);
316
  PORTB = (0 << PB5) | (0 << PB4) | (0 << PB2) | (1 << PB0) | 
317
          (1 << PB7) | (1 << PB1) | (1 << PB6) | (1 << PB3);
318
  PORTD = (0 << PD4) | (0 << PD3) | (0 << PD1) | (0 << PD0) |
319
          (1 << PD5) | (1 << PD2) | (1 << PD6);
320
321
  // next row
322
  active_row = (active_row+1) % 8;
323
  row = screen_mem[active_row];
324
325
  // output all columns, switch leds on.
326
  // column 1
327
  if ((row & 0x80) == 0x80) {
328
    PORTA |= (1 << PA0);    
329
  }
330
  // column 2
331
  if ((row & 0x40) == 0x40) {
332
    PORTB |= (1 << PB5);    
333
  }
334
  // column 3
335
  if ((row & 0x20) == 0x20) {
336
    PORTB |= (1 << PB4);    
337
  }
338
  // column 4
339
  if ((row & 0x10) == 0x10) {
340
    PORTD |= (1 << PD4);    
341
  }
342
  // column 5
343
  if ((row & 0x08) == 0x08) {
344
    PORTB |= (1 << PB2);    
345
  }
346
  // column 6
347
  if ((row & 0x04) == 0x04) {
348
    PORTD |= (1 << PD3);    
349
  }
350
  // column 7
351
  if ((row & 0x02) == 0x02) {
352
    PORTD |= (1 << PD1);    
353
  }
354
  // column 8
355
  if ((row & 0x01) == 0x01) {
356
    PORTD |= (1 << PD0);    
357
  }
358
359
  // activate row
360
  switch (active_row) {
361
  case 0:
362
    PORTD &= ~(1 << PD5);
363
    break;
364
  case 1:
365
    PORTA &= ~(1 << PA1);
366
    break;
367
  case 2:
368
    PORTB &= ~(1 << PB0);
369
    break;
370
  case 3:
371
    PORTD &= ~(1 << PD2);
372
    break;
373
  case 4:
374
    PORTB &= ~(1 << PB7);
375
    break;
376
  case 5:
377
    PORTB &= ~(1 << PB1);
378
    break;
379
  case 6:
380
    PORTB &= ~(1 << PB6);
381
    break;
382
  case 7:
383
    PORTB &= ~(1 << PB3);
384
    break;
385
  }
386
387
}
388
/*
389
 * Use this method, if you have a common cathode matrix.
390
 */
391
/*
392
void display_active_row(void) {
393
394
  uint8_t row;
395
396
  // shut down all rows and columns
397
  PORTB = 0x34; 
398
  PORTD = 0x1B; 
399
  PORTA = 0x01;
400
401
  // next row
402
  active_row = (active_row+1) % 8;
403
  row = screen_mem[active_row];
404
405
  // output all columns, switch leds on.
406
  // column 1
407
  if ((row & 0x80) == 0x80) {
408
    PORTA &= ~(1 << PA0);    
409
  }
410
  // column 2
411
  if ((row & 0x40) == 0x40) {
412
    PORTB &= ~(1 << PB5);    
413
  }
414
  // column 3
415
  if ((row & 0x20) == 0x20) {
416
    PORTB &= ~(1 << PB4);    
417
  }
418
  // column 4
419
  if ((row & 0x10) == 0x10) {
420
    PORTD &= ~(1 << PD4);    
421
  }
422
  // column 5
423
  if ((row & 0x08) == 0x08) {
424
    PORTB &= ~(1 << PB2);    
425
  }
426
  // column 6
427
  if ((row & 0x04) == 0x04) {
428
    PORTD &= ~(1 << PD3);    
429
  }
430
  // column 7
431
  if ((row & 0x02) == 0x02) {
432
    PORTD &= ~(1 << PD1);    
433
  }
434
  // column 8
435
  if ((row & 0x01) == 0x01) {
436
    PORTD &= ~(1 << PD0);    
437
  }
438
439
  // activate row
440
  switch (active_row) {
441
  case 0:
442
    PORTD |= (1 << PD5);
443
    break;
444
  case 1:
445
    PORTA |= (1 << PA1);
446
    break;
447
  case 2:
448
    PORTB |= (1 << PB0);
449
    break;
450
  case 3:
451
    PORTD |= (1 << PD2);
452
    break;
453
  case 4:
454
    PORTB |= (1 << PB7);
455
    break;
456
  case 5:
457
    PORTB |= (1 << PB1);
458
    break;
459
  case 6:
460
    PORTB |= (1 << PB6);
461
    break;
462
  case 7:
463
    PORTB |= (1 << PB3);
464
    break;
465
  }
466
467
}
468
*/
469
470
471
/*
472
 * show_char
473
 * Displays the actual message. 
474
 * Scrolls the screen to the left and draws new pixels on the right.
475
 */
476
void show_char() {
477
  uint8_t i;
478
  uint8_t b;
479
480
  // blit the screen to the left
481
  for (i = 0; i < 8; i++) {
482
    screen_mem[i] <<= 1; 
483
  }
484
  // advance a char if needed
485
  if (char_ptr == char_length) {
486
    message_ptr++;
487
    if (message_ptr == message_length) {
488
      message_ptr = 0;
489
      message_displayed++;
490
    }
491
    active_char = buffer[message_ptr] - CHAR_OFFSET;
492
    char_length = pgm_read_byte(&font[active_char * 4 + 3]);
493
    char_ptr = 0;
494
    return; // this makes the space between two chars
495
  }
496
  // read pixels for current column of char
497
  b = pgm_read_byte(&font[active_char * 4 + char_ptr++]);
498
  // write pixels into screen memory
499
  for (i = 0; i < 7; i++) {
500
    if ((b & (1 << i)) == (1 << i)) {
501
      screen_mem[i+1] |= 0x01;
502
    } 
503
  }
504
}
505
506
507
508
/*
509
 * clear_screen
510
 */
511
void clear_screen(void) {
512
  uint8_t i;
513
  for (i = 0; i < 8; i++) {
514
    screen_mem[i] = 0x00;
515
  }
516
}
517
518
519
520
/*
521
 * copy_to_buffer
522
 * Copies the given sprite from PROGMEM to RAM.
523
 */
524
void copy_to_buffer(const prog_uint8_t sprite[8]) {
525
  memcpy_P(buffer, sprite, 8);
526
}
527
528
529
530
/*
531
 * scroll_animation
532
 * Uses sprite_1 and sprite_2 to draw a simple animation.
533
 */
534
void scroll_animation(const prog_uint8_t sprite_1[8], const prog_uint8_t sprite_2[8]) {
535
  uint8_t i;
536
  int8_t x;
537
  for (i = 0; i < REPEAT_ANIMATION; i++) {
538
    copy_to_buffer(sprite_1);
539
    for (x = -8; x <= 0; x++) {
540
      copy_to_display(x, 0, buffer);
541
      delay_ms(ANIMATION_SCROLL_SPEED);
542
    }
543
    delay_ms(200);
544
    copy_to_buffer(sprite_2);
545
    copy_to_display(0, 0, buffer);
546
    delay_ms(200);
547
    copy_to_buffer(sprite_1);
548
    copy_to_display(0, 0, buffer);
549
    delay_ms(200);
550
    copy_to_buffer(sprite_2);
551
    copy_to_display(0, 0, buffer);
552
    delay_ms(200);
553
    copy_to_buffer(sprite_1);
554
    for (x = 0; x < 8; x++) {
555
      copy_to_display(x, 0, buffer);
556
      delay_ms(ANIMATION_SCROLL_SPEED);
557
    }
558
  }
559
}
560
561
562
563
int main(void) {
564
565
  uint8_t i = 0;
566
  uint8_t mode = 0;
567
  uint8_t cycle = 0;
568
569
  // timer 0 setup, prescaler 8
570
  TCCR0B |= (1 << CS01);
571
 
572
  // enable timer 0 interrupt
573
  TIMSK |= (1 << TOIE0);  
574
575
  // define outputs
576
  DDRA |= 0x03;  
577
  DDRB |= 0xFF;
578
  DDRD |= 0x3F;
579
  
580
  // shut down all rows and columns, enable column 1
581
  PORTA = (1 << PA0) | (1 << PA1);
582
  PORTB = (0 << PB5) | (0 << PB4) | (0 << PB2) | (1 << PB0) | 
583
          (1 << PB7) | (1 << PB1) | (1 << PB6) | (1 << PB3);
584
  PORTD = (0 << PD4) | (0 << PD3) | (0 << PD1) | (0 << PD0) |
585
          (1 << PD5) | (1 << PD2);
586
587
  // enable pull ups
588
  PORTD |= (1 << PD6);
589
590
  // say hello, toggle row 1 (pixel 0,0)
591
  for (i = 0; i < 5; i++) {
592
    PORTD &= ~(1 << PD5);
593
    _delay_ms(50);
594
    PORTD |= (1 << PD5);
595
    _delay_ms(50);
596
  }
597
598
  // read last mode from eeprom
599
  // 0 mean cycle through all modes and messages
600
  mode = eeprom_read_byte(&mode_ee);
601
  if ((mode == 0) || (mode >= (MAX_ANIMATIONS + MAX_MESSAGES + 1))) {
602
    mode = 1;
603
    cycle = 1;
604
  }
605
  eeprom_write_byte(&mode_ee, mode + 1);  
606
607
  sei();
608
609
  while (1) {
610
611
    switch (mode) {
612
    case 1:
613
      scroll_animation(sprite_00, sprite_01);
614
      break;
615
    case 2:
616
      for (i = 0; i < REPEAT_ANIMATION; i++) {
617
        copy_to_buffer(sprite_03);
618
        copy_to_display(0, 0, buffer);
619
        delay_ms(750);
620
        copy_to_buffer(sprite_02);        
621
        copy_to_display(0, 0, buffer);
622
        delay_ms(180);
623
      }
624
      break;
625
    case 3:
626
      scroll_animation(sprite_04, sprite_05);
627
      break;
628
    default:
629
      strcpy_P(buffer, (uint8_t*)pgm_read_word(&(messages[mode - (MAX_ANIMATIONS+1)])));
630
      message_length = strlen(buffer);
631
      while (message_displayed < REPEAT_TEXT) {
632
        show_char();
633
        delay_ms(TEXT_SCROLL_SPEED);
634
      }
635
      message_displayed = 0;
636
      break;
637
    }
638
639
    // cycle through all modes
640
    if (cycle) {
641
      mode++;
642
      clear_screen();
643
      if (mode >= (MAX_ANIMATIONS + MAX_MESSAGES + 1)) {
644
        mode = 1;
645
      }
646
    }
647
648
  }
649
650
  return 0;
651
652
}

von Markus (Gast)


Lesenswert?

sry nochmal das programm :
1
#include <avr/io.h>
2
#include <avr/pgmspace.h>
3
4
#ifndef FONT_H_
5
#define FONT_H_
6
7
#define MAX_CHARS 59
8
#define CHAR_OFFSET 0x20
9
10
const uint8_t font[] PROGMEM = {
11
  // 3 chars bitmap, 1 char length
12
   0x00, 0x00, 0x00, 0x01 ,    // 0x20, 32, ' '  
13
   0x17, 0x00, 0x00, 0x01 ,    // 0x21, 33, !  
14
   0x03, 0x00, 0x03, 0x03 ,    // 0x22, 34, "  
15
   0x00, 0x00, 0x00, 0x03 ,    // 0x23, 35, #  
16
   0x00, 0x00, 0x00, 0x03 ,    // 0x24, 36, $  
17
   0x00, 0x00, 0x00, 0x03 ,    // 0x25, 37, %  
18
   0x00, 0x00, 0x00, 0x03 ,    // 0x26, 38, &  
19
   0x03, 0x00, 0x00, 0x01 ,    // 0x27, 39, '  
20
   0x0e, 0x11, 0x00, 0x02 ,    // 0x28, 40, (  
21
   0x11, 0x0e, 0x00, 0x02 ,    // 0x29, 41, )  
22
   0x00, 0x00, 0x00, 0x03 ,    // 0x2A, 42, *  
23
   0x08, 0x1c, 0x08, 0x03 ,    // 0x2B, 43, +  
24
   0x18, 0x00, 0x00, 0x01 ,    // 0x2C, 44, ,  
25
   0x04, 0x04, 0x00, 0x03 ,    // 0x2D, 45, -  
26
   0x10, 0x00, 0x00, 0x01 ,    // 0x2E, 46, .  
27
   0x18, 0x04, 0x03, 0x03 ,    // 0x2F, 47, /  
28
   0x1f, 0x11, 0x1f, 0x03 ,    // 0x30, 48, 0
29
   0x01, 0x1f, 0x00, 0x02 ,    // 0x31, 49, 1
30
   0x1d, 0x15, 0x17, 0x03 ,    // 0x32, 50, 2
31
   0x15, 0x15, 0x0e, 0x03 ,    // 0x33, 51, 3
32
   0x0f, 0x08, 0x1f, 0x03 ,    // 0x34, 52, 4
33
   0x17, 0x15, 0x1d, 0x03 ,    // 0x35, 53, 5
34
   0x1f, 0x12, 0x1e, 0x03 ,    // 0x36, 54, 6
35
   0x11, 0x09, 0x07, 0x03 ,    // 0x37, 55, 7
36
   0x1f, 0x15, 0x1f, 0x03 ,    // 0x38, 56, 8
37
   0x0f, 0x09, 0x1f, 0x03 ,    // 0x39, 57, 9  
38
   0x0a, 0x00, 0x00, 0x01 ,    // 0x3A, 58, :
39
   0x1a, 0x00, 0x00, 0x01 ,    // 0x3B, 59, ;  
40
   0x08, 0x14, 0x00, 0x02 ,    // 0x3C, 60, <  
41
   0x14, 0x14, 0x00, 0x02 ,    // 0x3D, 61, =  
42
   0x14, 0x08, 0x00, 0x02 ,    // 0x3E, 62, >  
43
   0x15, 0x05, 0x02, 0x03 ,    // 0x3F, 63, ?  
44
   0x0e, 0x17, 0x16, 0x03 ,    // 0x40, 64, @  
45
   0x1f, 0x09, 0x1e, 0x03 ,    // 0x41, 65, A
46
   0x1f, 0x15, 0x0a, 0x03 ,    // 0x42, 66, B
47
   0x0e, 0x11, 0x11, 0x03 ,    // 0x43, 67, C
48
   0x1f, 0x11, 0x0e, 0x03 ,    // 0x44, 68, D
49
   0x0e, 0x15, 0x15, 0x03 ,    // 0x45, 69, E
50
   0x1e, 0x05, 0x05, 0x03 ,    // 0x46, 70, F
51
   0x0e, 0x11, 0x1d, 0x03 ,    // 0x47, 71, G
52
   0x1f, 0x04, 0x1f, 0x03 ,    // 0x48, 72, H
53
   0x1f, 0x00, 0x00, 0x01 ,    // 0x49, 73, I
54
   0x08, 0x10, 0x0f, 0x03 ,    // 0x4A, 74, J
55
   0x1f, 0x04, 0x1b, 0x03 ,    // 0x4B, 75, K
56
   0x0f, 0x10, 0x10, 0x03 ,    // 0x4C, 76, L
57
   0x1f, 0x02, 0x1f, 0x03 ,    // 0x4D, 77, M
58
   0x1f, 0x01, 0x1e, 0x03 ,    // 0x4E, 78, N
59
   0x0e, 0x11, 0x0e, 0x03 ,    // 0x4F, 79, O
60
   0x1f, 0x09, 0x06, 0x03 ,    // 0x50, 80, P
61
   0x06, 0x19, 0x06, 0x03 ,    // 0x51, 81, Q
62
   0x1f, 0x09, 0x16, 0x03 ,    // 0x52, 82, R
63
   0x12, 0x15, 0x09, 0x03 ,    // 0x53, 83, S
64
   0x01, 0x1f, 0x01, 0x03 ,    // 0x54, 84, T
65
   0x0f, 0x10, 0x0f, 0x03 ,    // 0x55, 85, U
66
   0x1f, 0x10, 0x0f, 0x03 ,    // 0x56, 86, V
67
   0x1f, 0x08, 0x1f, 0x03 ,    // 0x57, 87, W
68
   0x1b, 0x04, 0x1b, 0x03 ,    // 0x58, 88, X
69
   0x03, 0x1c, 0x03, 0x03 ,    // 0x59, 89, Y
70
   0x19, 0x15, 0x13, 0x03 ,    // 0x5A, 90, Z
71
   0x1f, 0x11, 0x00, 0x02 ,    // 0x5B, 91, [
72
   0x03, 0x04, 0x18, 0x03 ,    // 0x5C, 92, 
73
   0x11, 0x1f, 0x00, 0x02 ,    // 0x5D, 93, [
74
   0x11, 0x1f, 0x00, 0x02 ,    // 0x5E, 94, ^
75
   0x1f, 0x1f, 0x1f, 0x03     // 0x5F, 95, _, used as block, all on
76
};
77
78
#endif /*FONT_H_*/
79
80
#include <inttypes.h>
81
#include <stdlib.h>
82
#include <string.h>
83
#include <avr/io.h>
84
#include <avr/interrupt.h>
85
#include <avr/eeprom.h>
86
#include <util/delay.h>
87
#include <avr/pgmspace.h>
88
89
// Change these values to adjust scroll speeds and animation iterations
90
#define ANIMATION_SCROLL_SPEED 80  // how fast to scroll the animations
91
#define TEXT_SCROLL_SPEED 120      // how fast to scrill the text
92
#define REPEAT_ANIMATION 10        // how often to repeat the animation if in cycling mode
93
#define REPEAT_TEXT 5              // how often to repeat the text if in cycling mode
94
95
// How to add a new message:
96
// * add the new message (only upper case, see font.h)
97
// * adjust MAX_MESSAGES
98
// * add the new message to messages
99
// NOTE: messages may not be longer than 59 chars. Otherwise they will not fit in the buffer.
100
//                                              123456789012345678901234567890123456789012345678901234567890
101
const prog_char PROGMEM message_00[] PROGMEM = "  I LOVE U  ";
102
103
#define MAX_MESSAGES 12
104
PGM_P PROGMEM messages[] = {
105
  message_00
106
  
107
}; 
108
109
#define MAX_ANIMATIONS 1
110
111
112
const prog_uint8_t PROGMEM sprite_03[8] =
113
  {
114
    0x00,    // ________ 
115
    0x66,    // _XX__XX_
116
    0xFF,    // XXXXXXXX
117
    0xFF,    // XXXXXXXX
118
    0xFF,    // XXXXXXXX
119
    0x7E,    // _XXXXXX_
120
    0x3C,    // __XXXX__
121
    0x18     // ___XX___
122
  };
123
124
125
126
127
uint8_t mode_ee EEMEM = 0;                      // stores the mode in eeprom
128
static uint8_t screen_mem[8];      // screen memory
129
static uint8_t active_row;      // active row
130
static uint8_t buffer[60];                      // stores the active message or sprite
131
static uint8_t message_ptr = 0;                 // points to the active char in the message
132
static uint8_t message_displayed = 0;           // how often has the message been displayed?
133
static uint8_t active_char = 0;                 // stores the active char
134
static uint8_t message_length = 0;              // stores the length of the active message
135
static uint8_t char_ptr = 0;                    // points to the active col in the char
136
static uint8_t char_length = 0;                 // stores the length of the active char
137
static volatile uint16_t counter = 0;           // used for delay function
138
139
// prototypes
140
void delay_ms(uint16_t delay);
141
void copy_to_display(int8_t x, int8_t y, uint8_t sprite[]);
142
void display_active_row(void);
143
void show_char();
144
void clear_screen(void);
145
void copy_to_buffer(const prog_uint8_t sprite[8]);
146
void scroll_animation(const prog_uint8_t sprite_1[], const prog_uint8_t sprite_2[]);
147
148
149
150
/*
151
 * ISR TIMER0_OVF_vect
152
 * Handles overflow interrupts of timer 0.
153
 *
154
 * 4MHz
155
 * ----
156
 * Prescaler 8 ==> 1953.1 Hz
157
 * Complete display = 244 Hz
158
 *
159
 */
160
ISR(TIMER0_OVF_vect) {  
161
  display_active_row();
162
  counter++;
163
}
164
165
166
167
/*
168
 * delay_ms
169
 * Uses the counter that is incremented by the ISR.
170
 * Max delay is 32767ms.
171
 */
172
void delay_ms(uint16_t delay) {
173
  while (!(PIND & (1 << PD6))) {}   // used to stop the animation when PD6 goes LOW
174
  uint16_t t = delay * 2;
175
  counter = 0;
176
  while (counter < t) {}
177
}
178
179
180
181
/*
182
 * copy_to_display
183
 * Copies sprite data to the screen memory at the given position. 
184
 */
185
void copy_to_display(int8_t x, int8_t y, uint8_t sprite[8]) {
186
  int8_t i, t;
187
  uint8_t row;
188
  for (i = 0; i < 8; i++) {
189
    t = i-y;
190
    row = ((t >= 0) && (t < 8)) ? sprite[t] : 0x00;
191
    row = (x >= 0) ? (row >> x) : (row << -x);
192
    screen_mem[i] = row;
193
  }
194
}
195
196
197
198
/*
199
 * display_active_col
200
 * Deactivates the active column and displays the next one.
201
 * Data is read from screen_mem.
202
 *
203
 *      ATtiny2313
204
 * 16 - PD0    PB7 - 1
205
 * 15 - PD1    PB6 - 2
206
 * 14 - PA1    PB5 - 3
207
 * 13 - PA0    PB4 - 4
208
 * 12 - PD2    PB3 - 5
209
 * 11 - PD3    PB2 - 6
210
 * 10 - PD4    PB1 - 7
211
 *  9 - PD5    PB0 - 8
212
 *
213
 * NFM-12883 common anode          |
214
 *     A0B5B4D4B2D3D1D0      +-----+
215
 * PD5 o o o o o o o o       |     |
216
 * PA1 o o o o o o o o      _+_    |
217
 * PB0 o o o o o o o o      \ /    |
218
 * PD2 o o o o o o o o     __V__   |
219
 * PB7 o o o o o o o o       |     |
220
 * PB1 o o o o o o o o    ---+-----C---
221
 * PB6 o o o o o o o o             |
222
 * PB3 o o o o o o o o
223
 *
224
 */
225
void display_active_row(void) {
226
227
  uint8_t row;
228
229
  // shut down all rows and columns
230
  PORTA = (0 << PA0) | (1 << PA1);
231
  PORTB = (0 << PB5) | (0 << PB4) | (0 << PB2) | (1 << PB0) | 
232
          (1 << PB7) | (1 << PB1) | (1 << PB6) | (1 << PB3);
233
  PORTD = (0 << PD4) | (0 << PD3) | (0 << PD1) | (0 << PD0) |
234
          (1 << PD5) | (1 << PD2) | (1 << PD6);
235
236
  // next row
237
  active_row = (active_row+1) % 8;
238
  row = screen_mem[active_row];
239
240
  // output all columns, switch leds on.
241
  // column 1
242
  if ((row & 0x80) == 0x80) {
243
    PORTA |= (1 << PA0);    
244
  }
245
  // column 2
246
  if ((row & 0x40) == 0x40) {
247
    PORTB |= (1 << PB5);    
248
  }
249
  // column 3
250
  if ((row & 0x20) == 0x20) {
251
    PORTB |= (1 << PB4);    
252
  }
253
  // column 4
254
  if ((row & 0x10) == 0x10) {
255
    PORTD |= (1 << PD4);    
256
  }
257
  // column 5
258
  if ((row & 0x08) == 0x08) {
259
    PORTB |= (1 << PB2);    
260
  }
261
  // column 6
262
  if ((row & 0x04) == 0x04) {
263
    PORTD |= (1 << PD3);    
264
  }
265
  // column 7
266
  if ((row & 0x02) == 0x02) {
267
    PORTD |= (1 << PD1);    
268
  }
269
  // column 8
270
  if ((row & 0x01) == 0x01) {
271
    PORTD |= (1 << PD0);    
272
  }
273
274
  // activate row
275
  switch (active_row) {
276
  case 0:
277
    PORTD &= ~(1 << PD5);
278
    break;
279
  case 1:
280
    PORTA &= ~(1 << PA1);
281
    break;
282
  case 2:
283
    PORTB &= ~(1 << PB0);
284
    break;
285
  case 3:
286
    PORTD &= ~(1 << PD2);
287
    break;
288
  case 4:
289
    PORTB &= ~(1 << PB7);
290
    break;
291
  case 5:
292
    PORTB &= ~(1 << PB1);
293
    break;
294
  case 6:
295
    PORTB &= ~(1 << PB6);
296
    break;
297
  case 7:
298
    PORTB &= ~(1 << PB3);
299
    break;
300
  }
301
302
}
303
/*
304
 * Use this method, if you have a common cathode matrix.
305
 */
306
/*
307
void display_active_row(void) {
308
309
  uint8_t row;
310
311
  // shut down all rows and columns
312
  PORTB = 0x34; 
313
  PORTD = 0x1B; 
314
  PORTA = 0x01;
315
316
  // next row
317
  active_row = (active_row+1) % 8;
318
  row = screen_mem[active_row];
319
320
  // output all columns, switch leds on.
321
  // column 1
322
  if ((row & 0x80) == 0x80) {
323
    PORTA &= ~(1 << PA0);    
324
  }
325
  // column 2
326
  if ((row & 0x40) == 0x40) {
327
    PORTB &= ~(1 << PB5);    
328
  }
329
  // column 3
330
  if ((row & 0x20) == 0x20) {
331
    PORTB &= ~(1 << PB4);    
332
  }
333
  // column 4
334
  if ((row & 0x10) == 0x10) {
335
    PORTD &= ~(1 << PD4);    
336
  }
337
  // column 5
338
  if ((row & 0x08) == 0x08) {
339
    PORTB &= ~(1 << PB2);    
340
  }
341
  // column 6
342
  if ((row & 0x04) == 0x04) {
343
    PORTD &= ~(1 << PD3);    
344
  }
345
  // column 7
346
  if ((row & 0x02) == 0x02) {
347
    PORTD &= ~(1 << PD1);    
348
  }
349
  // column 8
350
  if ((row & 0x01) == 0x01) {
351
    PORTD &= ~(1 << PD0);    
352
  }
353
354
  // activate row
355
  switch (active_row) {
356
  case 0:
357
    PORTD |= (1 << PD5);
358
    break;
359
  case 1:
360
    PORTA |= (1 << PA1);
361
    break;
362
  case 2:
363
    PORTB |= (1 << PB0);
364
    break;
365
  case 3:
366
    PORTD |= (1 << PD2);
367
    break;
368
  case 4:
369
    PORTB |= (1 << PB7);
370
    break;
371
  case 5:
372
    PORTB |= (1 << PB1);
373
    break;
374
  case 6:
375
    PORTB |= (1 << PB6);
376
    break;
377
  case 7:
378
    PORTB |= (1 << PB3);
379
    break;
380
  }
381
382
}
383
*/
384
385
386
/*
387
 * show_char
388
 * Displays the actual message. 
389
 * Scrolls the screen to the left and draws new pixels on the right.
390
 */
391
void show_char() {
392
  uint8_t i;
393
  uint8_t b;
394
395
  // blit the screen to the left
396
  for (i = 0; i < 8; i++) {
397
    screen_mem[i] <<= 1; 
398
  }
399
  // advance a char if needed
400
  if (char_ptr == char_length) {
401
    message_ptr++;
402
    if (message_ptr == message_length) {
403
      message_ptr = 0;
404
      message_displayed++;
405
    }
406
    active_char = buffer[message_ptr] - CHAR_OFFSET;
407
    char_length = pgm_read_byte(&font[active_char * 4 + 3]);
408
    char_ptr = 0;
409
    return; // this makes the space between two chars
410
  }
411
  // read pixels for current column of char
412
  b = pgm_read_byte(&font[active_char * 4 + char_ptr++]);
413
  // write pixels into screen memory
414
  for (i = 0; i < 7; i++) {
415
    if ((b & (1 << i)) == (1 << i)) {
416
      screen_mem[i+1] |= 0x01;
417
    } 
418
  }
419
}
420
421
422
423
/*
424
 * clear_screen
425
 */
426
void clear_screen(void) {
427
  uint8_t i;
428
  for (i = 0; i < 8; i++) {
429
    screen_mem[i] = 0x00;
430
  }
431
}
432
433
434
435
/*
436
 * copy_to_buffer
437
 * Copies the given sprite from PROGMEM to RAM.
438
 */
439
void copy_to_buffer(const prog_uint8_t sprite[8]) {
440
  memcpy_P(buffer, sprite, 8);
441
}
442
443
444
445
/*
446
 * scroll_animation
447
 * Uses sprite_1 and sprite_2 to draw a simple animation.
448
 */
449
void scroll_animation(const prog_uint8_t sprite_1[8], const prog_uint8_t sprite_2[8]) {
450
  uint8_t i;
451
  int8_t x;
452
  for (i = 0; i < REPEAT_ANIMATION; i++) {
453
    copy_to_buffer(sprite_1);
454
    for (x = -8; x <= 0; x++) {
455
      copy_to_display(x, 0, buffer);
456
      delay_ms(ANIMATION_SCROLL_SPEED);
457
    }
458
    delay_ms(200);
459
    copy_to_buffer(sprite_2);
460
    copy_to_display(0, 0, buffer);
461
    delay_ms(200);
462
    copy_to_buffer(sprite_1);
463
    copy_to_display(0, 0, buffer);
464
    delay_ms(200);
465
    copy_to_buffer(sprite_2);
466
    copy_to_display(0, 0, buffer);
467
    delay_ms(200);
468
    copy_to_buffer(sprite_1);
469
    for (x = 0; x < 8; x++) {
470
      copy_to_display(x, 0, buffer);
471
      delay_ms(ANIMATION_SCROLL_SPEED);
472
    }
473
  }
474
}
475
476
477
478
int main(void) {
479
480
  uint8_t i = 0;
481
  uint8_t mode = 0;
482
  uint8_t cycle = 0;
483
484
  // timer 0 setup, prescaler 8
485
  TCCR0B |= (1 << CS01);
486
 
487
  // enable timer 0 interrupt
488
  TIMSK |= (1 << TOIE0);  
489
490
  // define outputs
491
  DDRA |= 0x03;  
492
  DDRB |= 0xFF;
493
  DDRD |= 0x3F;
494
  
495
  // shut down all rows and columns, enable column 1
496
  PORTA = (1 << PA0) | (1 << PA1);
497
  PORTB = (0 << PB5) | (0 << PB4) | (0 << PB2) | (1 << PB0) | 
498
          (1 << PB7) | (1 << PB1) | (1 << PB6) | (1 << PB3);
499
  PORTD = (0 << PD4) | (0 << PD3) | (0 << PD1) | (0 << PD0) |
500
          (1 << PD5) | (1 << PD2);
501
502
  // enable pull ups
503
  PORTD |= (1 << PD6);
504
505
  // say hello, toggle row 1 (pixel 0,0)
506
  for (i = 0; i < 5; i++) {
507
    PORTD &= ~(1 << PD5);
508
    _delay_ms(50);
509
    PORTD |= (1 << PD5);
510
    _delay_ms(50);
511
  }
512
513
  // read last mode from eeprom
514
  // 0 mean cycle through all modes and messages
515
  mode = eeprom_read_byte(&mode_ee);
516
  if ((mode == 0) || (mode >= (MAX_ANIMATIONS + MAX_MESSAGES + 1))) {
517
    mode = 1;
518
    cycle = 1;
519
  }
520
  eeprom_write_byte(&mode_ee, mode + 1);  
521
522
  sei();
523
524
  while (1) {
525
526
    switch (mode) {
527
    case 1:
528
      break;
529
    case 2:
530
      for (i = 0; i < REPEAT_ANIMATION; i++) {
531
        copy_to_buffer(sprite_03);
532
        copy_to_display(0, 0, buffer);
533
        delay_ms(750);
534
      }
535
      break;
536
    case 3:
537
      break;
538
    default:
539
      while (message_displayed < REPEAT_TEXT) {
540
        show_char();
541
        delay_ms(TEXT_SCROLL_SPEED);
542
      }
543
      message_displayed = 0;
544
      break;
545
    }
546
547
    // cycle through all modes
548
    if (cycle) {
549
      mode++;
550
      clear_screen();
551
      if (mode >= (MAX_ANIMATIONS + MAX_MESSAGES + 1)) {
552
        mode = 1;
553
      }
554
    }
555
556
  }
557
558
  return 0;
559
560
}

von Maddin (Gast)


Lesenswert?

reinfunken und gucken!

wo kommt das denn her? Es gibt schon noch 2 3 Codeschnipsel mehr hier...

M.

von Lehrmann M. (ubimbo)


Lesenswert?

Markus schrieb:
> Hab das Programm von dieser seite ein bisschen gekürzt. ist das so
> korrekt?

Gibt es Probleme oder warum schreibst du das?
Ich meine was erwartest du?
Dass wir das ganze Programm durchdenken ohne konkrete Problemstellung 
und vernünfigen Schaltplan... was erhoffst du dir?

Wenn du wissen möchtest ob es funktioniert - probier es aus ... kaputt 
machen kannst du wohl kaum was ...

von Markus (Gast)


Lesenswert?

so hatte ausversehen das falsche geschickt ^^
also ich weiß jetzt nicht wie ich das auf eine 5x7 matrix umschreiben 
soll. wie kann ich das am besten umsetzen?
1
#include <avr/io.h>
2
#include <avr/pgmspace.h>
3
4
#ifndef FONT_H_
5
#define FONT_H_
6
7
#define MAX_CHARS 59
8
#define CHAR_OFFSET 0x20
9
10
const uint8_t font[] PROGMEM = {
11
  // 3 chars bitmap, 1 char length
12
   0x00, 0x00, 0x00, 0x01 ,    // 0x20, 32, ' '  
13
   0x17, 0x00, 0x00, 0x01 ,    // 0x21, 33, !  
14
   0x03, 0x00, 0x03, 0x03 ,    // 0x22, 34, "  
15
   0x00, 0x00, 0x00, 0x03 ,    // 0x23, 35, #  
16
   0x00, 0x00, 0x00, 0x03 ,    // 0x24, 36, $  
17
   0x00, 0x00, 0x00, 0x03 ,    // 0x25, 37, %  
18
   0x00, 0x00, 0x00, 0x03 ,    // 0x26, 38, &  
19
   0x03, 0x00, 0x00, 0x01 ,    // 0x27, 39, '  
20
   0x0e, 0x11, 0x00, 0x02 ,    // 0x28, 40, (  
21
   0x11, 0x0e, 0x00, 0x02 ,    // 0x29, 41, )  
22
   0x00, 0x00, 0x00, 0x03 ,    // 0x2A, 42, *  
23
   0x08, 0x1c, 0x08, 0x03 ,    // 0x2B, 43, +  
24
   0x18, 0x00, 0x00, 0x01 ,    // 0x2C, 44, ,  
25
   0x04, 0x04, 0x00, 0x03 ,    // 0x2D, 45, -  
26
   0x10, 0x00, 0x00, 0x01 ,    // 0x2E, 46, .  
27
   0x18, 0x04, 0x03, 0x03 ,    // 0x2F, 47, /  
28
   0x1f, 0x11, 0x1f, 0x03 ,    // 0x30, 48, 0
29
   0x01, 0x1f, 0x00, 0x02 ,    // 0x31, 49, 1
30
   0x1d, 0x15, 0x17, 0x03 ,    // 0x32, 50, 2
31
   0x15, 0x15, 0x0e, 0x03 ,    // 0x33, 51, 3
32
   0x0f, 0x08, 0x1f, 0x03 ,    // 0x34, 52, 4
33
   0x17, 0x15, 0x1d, 0x03 ,    // 0x35, 53, 5
34
   0x1f, 0x12, 0x1e, 0x03 ,    // 0x36, 54, 6
35
   0x11, 0x09, 0x07, 0x03 ,    // 0x37, 55, 7
36
   0x1f, 0x15, 0x1f, 0x03 ,    // 0x38, 56, 8
37
   0x0f, 0x09, 0x1f, 0x03 ,    // 0x39, 57, 9  
38
   0x0a, 0x00, 0x00, 0x01 ,    // 0x3A, 58, :
39
   0x1a, 0x00, 0x00, 0x01 ,    // 0x3B, 59, ;  
40
   0x08, 0x14, 0x00, 0x02 ,    // 0x3C, 60, <  
41
   0x14, 0x14, 0x00, 0x02 ,    // 0x3D, 61, =  
42
   0x14, 0x08, 0x00, 0x02 ,    // 0x3E, 62, >  
43
   0x15, 0x05, 0x02, 0x03 ,    // 0x3F, 63, ?  
44
   0x0e, 0x17, 0x16, 0x03 ,    // 0x40, 64, @  
45
   0x1f, 0x09, 0x1e, 0x03 ,    // 0x41, 65, A
46
   0x1f, 0x15, 0x0a, 0x03 ,    // 0x42, 66, B
47
   0x0e, 0x11, 0x11, 0x03 ,    // 0x43, 67, C
48
   0x1f, 0x11, 0x0e, 0x03 ,    // 0x44, 68, D
49
   0x0e, 0x15, 0x15, 0x03 ,    // 0x45, 69, E
50
   0x1e, 0x05, 0x05, 0x03 ,    // 0x46, 70, F
51
   0x0e, 0x11, 0x1d, 0x03 ,    // 0x47, 71, G
52
   0x1f, 0x04, 0x1f, 0x03 ,    // 0x48, 72, H
53
   0x1f, 0x00, 0x00, 0x01 ,    // 0x49, 73, I
54
   0x08, 0x10, 0x0f, 0x03 ,    // 0x4A, 74, J
55
   0x1f, 0x04, 0x1b, 0x03 ,    // 0x4B, 75, K
56
   0x0f, 0x10, 0x10, 0x03 ,    // 0x4C, 76, L
57
   0x1f, 0x02, 0x1f, 0x03 ,    // 0x4D, 77, M
58
   0x1f, 0x01, 0x1e, 0x03 ,    // 0x4E, 78, N
59
   0x0e, 0x11, 0x0e, 0x03 ,    // 0x4F, 79, O
60
   0x1f, 0x09, 0x06, 0x03 ,    // 0x50, 80, P
61
   0x06, 0x19, 0x06, 0x03 ,    // 0x51, 81, Q
62
   0x1f, 0x09, 0x16, 0x03 ,    // 0x52, 82, R
63
   0x12, 0x15, 0x09, 0x03 ,    // 0x53, 83, S
64
   0x01, 0x1f, 0x01, 0x03 ,    // 0x54, 84, T
65
   0x0f, 0x10, 0x0f, 0x03 ,    // 0x55, 85, U
66
   0x1f, 0x10, 0x0f, 0x03 ,    // 0x56, 86, V
67
   0x1f, 0x08, 0x1f, 0x03 ,    // 0x57, 87, W
68
   0x1b, 0x04, 0x1b, 0x03 ,    // 0x58, 88, X
69
   0x03, 0x1c, 0x03, 0x03 ,    // 0x59, 89, Y
70
   0x19, 0x15, 0x13, 0x03 ,    // 0x5A, 90, Z
71
   0x1f, 0x11, 0x00, 0x02 ,    // 0x5B, 91, [
72
   0x03, 0x04, 0x18, 0x03 ,    // 0x5C, 92, 
73
   0x11, 0x1f, 0x00, 0x02 ,    // 0x5D, 93, [
74
   0x11, 0x1f, 0x00, 0x02 ,    // 0x5E, 94, ^
75
   0x1f, 0x1f, 0x1f, 0x03     // 0x5F, 95, _, used as block, all on
76
};
77
78
#endif /*FONT_H_*/
79
80
#include <inttypes.h>
81
#include <stdlib.h>
82
#include <string.h>
83
#include <avr/io.h>
84
#include <avr/interrupt.h>
85
#include <avr/eeprom.h>
86
#include <util/delay.h>
87
#include <avr/pgmspace.h>
88
89
// Change these values to adjust scroll speeds and animation iterations
90
#define ANIMATION_SCROLL_SPEED 80  // how fast to scroll the animations
91
#define TEXT_SCROLL_SPEED 120      // how fast to scrill the text
92
#define REPEAT_ANIMATION 10        // how often to repeat the animation if in cycling mode
93
#define REPEAT_TEXT 5              // how often to repeat the text if in cycling mode
94
95
// How to add a new message:
96
// * add the new message (only upper case, see font.h)
97
// * adjust MAX_MESSAGES
98
// * add the new message to messages
99
// NOTE: messages may not be longer than 59 chars. Otherwise they will not fit in the buffer.
100
//                                              123456789012345678901234567890123456789012345678901234567890
101
const prog_char PROGMEM message_00[] PROGMEM = "  I LOVE U  ";
102
103
#define MAX_MESSAGES 12
104
PGM_P PROGMEM messages[] = {
105
  message_00
106
  
107
}; 
108
109
#define MAX_ANIMATIONS 1
110
111
112
const prog_uint8_t PROGMEM sprite_03[8] =
113
  {
114
    0x00,    // ________ 
115
    0x66,    // _XX__XX_
116
    0xFF,    // XXXXXXXX
117
    0xFF,    // XXXXXXXX
118
    0xFF,    // XXXXXXXX
119
    0x7E,    // _XXXXXX_
120
    0x3C,    // __XXXX__
121
    0x18     // ___XX___
122
  };
123
124
125
126
127
uint8_t mode_ee EEMEM = 0;                      // stores the mode in eeprom
128
static uint8_t screen_mem[8];      // screen memory
129
static uint8_t active_row;      // active row
130
static uint8_t buffer[60];                      // stores the active message or sprite
131
static uint8_t message_ptr = 0;                 // points to the active char in the message
132
static uint8_t message_displayed = 0;           // how often has the message been displayed?
133
static uint8_t active_char = 0;                 // stores the active char
134
static uint8_t message_length = 0;              // stores the length of the active message
135
static uint8_t char_ptr = 0;                    // points to the active col in the char
136
static uint8_t char_length = 0;                 // stores the length of the active char
137
static volatile uint16_t counter = 0;           // used for delay function
138
139
// prototypes
140
void delay_ms(uint16_t delay);
141
void copy_to_display(int8_t x, int8_t y, uint8_t sprite[]);
142
void display_active_row(void);
143
void show_char();
144
void clear_screen(void);
145
void copy_to_buffer(const prog_uint8_t sprite[8]);
146
void scroll_animation(const prog_uint8_t sprite_1[], const prog_uint8_t sprite_2[]);
147
148
149
150
/*
151
 * ISR TIMER0_OVF_vect
152
 * Handles overflow interrupts of timer 0.
153
 *
154
 * 4MHz
155
 * ----
156
 * Prescaler 8 ==> 1953.1 Hz
157
 * Complete display = 244 Hz
158
 *
159
 */
160
ISR(TIMER0_OVF_vect) {  
161
  display_active_row();
162
  counter++;
163
}
164
165
166
167
/*
168
 * delay_ms
169
 * Uses the counter that is incremented by the ISR.
170
 * Max delay is 32767ms.
171
 */
172
void delay_ms(uint16_t delay) {
173
  while (!(PIND & (1 << PD6))) {}   // used to stop the animation when PD6 goes LOW
174
  uint16_t t = delay * 2;
175
  counter = 0;
176
  while (counter < t) {}
177
}
178
179
180
181
/*
182
 * copy_to_display
183
 * Copies sprite data to the screen memory at the given position. 
184
 */
185
void copy_to_display(int8_t x, int8_t y, uint8_t sprite[8]) {
186
  int8_t i, t;
187
  uint8_t row;
188
  for (i = 0; i < 8; i++) {
189
    t = i-y;
190
    row = ((t >= 0) && (t < 8)) ? sprite[t] : 0x00;
191
    row = (x >= 0) ? (row >> x) : (row << -x);
192
    screen_mem[i] = row;
193
  }
194
}
195
196
197
198
/*
199
 * display_active_col
200
 * Deactivates the active column and displays the next one.
201
 * Data is read from screen_mem.
202
 *
203
 *      ATtiny2313
204
 * 16 - PD0    PB7 - 1
205
 * 15 - PD1    PB6 - 2
206
 * 14 - PA1    PB5 - 3
207
 * 13 - PA0    PB4 - 4
208
 * 12 - PD2    PB3 - 5
209
 * 11 - PD3    PB2 - 6
210
 * 10 - PD4    PB1 - 7
211
 *  9 - PD5    PB0 - 8
212
 *
213
 * NFM-12883 common anode          |
214
 *     A0B5B4D4B2D3D1D0      +-----+
215
 * PD5 o o o o o o o o       |     |
216
 * PA1 o o o o o o o o      _+_    |
217
 * PB0 o o o o o o o o      \ /    |
218
 * PD2 o o o o o o o o     __V__   |
219
 * PB7 o o o o o o o o       |     |
220
 * PB1 o o o o o o o o    ---+-----C---
221
 * PB6 o o o o o o o o             |
222
 * PB3 o o o o o o o o
223
 *
224
 */
225
void display_active_row(void) {
226
227
  uint8_t row;
228
229
  // shut down all rows and columns
230
  PORTA = (0 << PA0) | (1 << PA1);
231
  PORTB = (0 << PB5) | (0 << PB4) | (0 << PB2) | (1 << PB0) | 
232
          (1 << PB7) | (1 << PB1) | (1 << PB6) | (1 << PB3);
233
  PORTD = (0 << PD4) | (0 << PD3) | (0 << PD1) | (0 << PD0) |
234
          (1 << PD5) | (1 << PD2) | (1 << PD6);
235
236
  // next row
237
  active_row = (active_row+1) % 8;
238
  row = screen_mem[active_row];
239
240
  // output all columns, switch leds on.
241
  // column 1
242
  if ((row & 0x80) == 0x80) {
243
    PORTA |= (1 << PA0);    
244
  }
245
  // column 2
246
  if ((row & 0x40) == 0x40) {
247
    PORTB |= (1 << PB5);    
248
  }
249
  // column 3
250
  if ((row & 0x20) == 0x20) {
251
    PORTB |= (1 << PB4);    
252
  }
253
  // column 4
254
  if ((row & 0x10) == 0x10) {
255
    PORTD |= (1 << PD4);    
256
  }
257
  // column 5
258
  if ((row & 0x08) == 0x08) {
259
    PORTB |= (1 << PB2);    
260
  }
261
  // column 6
262
  if ((row & 0x04) == 0x04) {
263
    PORTD |= (1 << PD3);    
264
  }
265
  // column 7
266
  if ((row & 0x02) == 0x02) {
267
    PORTD |= (1 << PD1);    
268
  }
269
  // column 8
270
  if ((row & 0x01) == 0x01) {
271
    PORTD |= (1 << PD0);    
272
  }
273
274
  // activate row
275
  switch (active_row) {
276
  case 0:
277
    PORTD &= ~(1 << PD5);
278
    break;
279
  case 1:
280
    PORTA &= ~(1 << PA1);
281
    break;
282
  case 2:
283
    PORTB &= ~(1 << PB0);
284
    break;
285
  case 3:
286
    PORTD &= ~(1 << PD2);
287
    break;
288
  case 4:
289
    PORTB &= ~(1 << PB7);
290
    break;
291
  case 5:
292
    PORTB &= ~(1 << PB1);
293
    break;
294
  case 6:
295
    PORTB &= ~(1 << PB6);
296
    break;
297
  case 7:
298
    PORTB &= ~(1 << PB3);
299
    break;
300
  }
301
302
}
303
/*
304
 * Use this method, if you have a common cathode matrix.
305
 */
306
/*
307
void display_active_row(void) {
308
309
  uint8_t row;
310
311
  // shut down all rows and columns
312
  PORTB = 0x34; 
313
  PORTD = 0x1B; 
314
  PORTA = 0x01;
315
316
  // next row
317
  active_row = (active_row+1) % 8;
318
  row = screen_mem[active_row];
319
320
  // output all columns, switch leds on.
321
  // column 1
322
  if ((row & 0x80) == 0x80) {
323
    PORTA &= ~(1 << PA0);    
324
  }
325
  // column 2
326
  if ((row & 0x40) == 0x40) {
327
    PORTB &= ~(1 << PB5);    
328
  }
329
  // column 3
330
  if ((row & 0x20) == 0x20) {
331
    PORTB &= ~(1 << PB4);    
332
  }
333
  // column 4
334
  if ((row & 0x10) == 0x10) {
335
    PORTD &= ~(1 << PD4);    
336
  }
337
  // column 5
338
  if ((row & 0x08) == 0x08) {
339
    PORTB &= ~(1 << PB2);    
340
  }
341
  // column 6
342
  if ((row & 0x04) == 0x04) {
343
    PORTD &= ~(1 << PD3);    
344
  }
345
  // column 7
346
  if ((row & 0x02) == 0x02) {
347
    PORTD &= ~(1 << PD1);    
348
  }
349
  // column 8
350
  if ((row & 0x01) == 0x01) {
351
    PORTD &= ~(1 << PD0);    
352
  }
353
354
  // activate row
355
  switch (active_row) {
356
  case 0:
357
    PORTD |= (1 << PD5);
358
    break;
359
  case 1:
360
    PORTA |= (1 << PA1);
361
    break;
362
  case 2:
363
    PORTB |= (1 << PB0);
364
    break;
365
  case 3:
366
    PORTD |= (1 << PD2);
367
    break;
368
  case 4:
369
    PORTB |= (1 << PB7);
370
    break;
371
  case 5:
372
    PORTB |= (1 << PB1);
373
    break;
374
  case 6:
375
    PORTB |= (1 << PB6);
376
    break;
377
  case 7:
378
    PORTB |= (1 << PB3);
379
    break;
380
  }
381
382
}
383
*/
384
385
386
/*
387
 * show_char
388
 * Displays the actual message. 
389
 * Scrolls the screen to the left and draws new pixels on the right.
390
 */
391
void show_char() {
392
  uint8_t i;
393
  uint8_t b;
394
395
  // blit the screen to the left
396
  for (i = 0; i < 8; i++) {
397
    screen_mem[i] <<= 1; 
398
  }
399
  // advance a char if needed
400
  if (char_ptr == char_length) {
401
    message_ptr++;
402
    if (message_ptr == message_length) {
403
      message_ptr = 0;
404
      message_displayed++;
405
    }
406
    active_char = buffer[message_ptr] - CHAR_OFFSET;
407
    char_length = pgm_read_byte(&font[active_char * 4 + 3]);
408
    char_ptr = 0;
409
    return; // this makes the space between two chars
410
  }
411
  // read pixels for current column of char
412
  b = pgm_read_byte(&font[active_char * 4 + char_ptr++]);
413
  // write pixels into screen memory
414
  for (i = 0; i < 7; i++) {
415
    if ((b & (1 << i)) == (1 << i)) {
416
      screen_mem[i+1] |= 0x01;
417
    } 
418
  }
419
}
420
421
422
423
/*
424
 * clear_screen
425
 */
426
void clear_screen(void) {
427
  uint8_t i;
428
  for (i = 0; i < 8; i++) {
429
    screen_mem[i] = 0x00;
430
  }
431
}
432
433
434
435
/*
436
 * copy_to_buffer
437
 * Copies the given sprite from PROGMEM to RAM.
438
 */
439
void copy_to_buffer(const prog_uint8_t sprite[8]) {
440
  memcpy_P(buffer, sprite, 8);
441
}
442
443
444
445
/*
446
 * scroll_animation
447
 * Uses sprite_1 and sprite_2 to draw a simple animation.
448
 */
449
void scroll_animation(const prog_uint8_t sprite_1[8], const prog_uint8_t sprite_2[8]) {
450
  uint8_t i;
451
  int8_t x;
452
  for (i = 0; i < REPEAT_ANIMATION; i++) {
453
    copy_to_buffer(sprite_1);
454
    for (x = -8; x <= 0; x++) {
455
      copy_to_display(x, 0, buffer);
456
      delay_ms(ANIMATION_SCROLL_SPEED);
457
    }
458
    delay_ms(200);
459
    copy_to_buffer(sprite_2);
460
    copy_to_display(0, 0, buffer);
461
    delay_ms(200);
462
    copy_to_buffer(sprite_1);
463
    copy_to_display(0, 0, buffer);
464
    delay_ms(200);
465
    copy_to_buffer(sprite_2);
466
    copy_to_display(0, 0, buffer);
467
    delay_ms(200);
468
    copy_to_buffer(sprite_1);
469
    for (x = 0; x < 8; x++) {
470
      copy_to_display(x, 0, buffer);
471
      delay_ms(ANIMATION_SCROLL_SPEED);
472
    }
473
  }
474
}
475
476
477
478
int main(void) {
479
480
  uint8_t i = 0;
481
  uint8_t mode = 0;
482
  uint8_t cycle = 0;
483
484
  // timer 0 setup, prescaler 8
485
  TCCR0B |= (1 << CS01);
486
 
487
  // enable timer 0 interrupt
488
  TIMSK |= (1 << TOIE0);  
489
490
  // define outputs
491
  DDRA |= 0x03;  
492
  DDRB |= 0xFF;
493
  DDRD |= 0x3F;
494
  
495
  // shut down all rows and columns, enable column 1
496
  PORTA = (1 << PA0) | (1 << PA1);
497
  PORTB = (0 << PB5) | (0 << PB4) | (0 << PB2) | (1 << PB0) | 
498
          (1 << PB7) | (1 << PB1) | (1 << PB6) | (1 << PB3);
499
  PORTD = (0 << PD4) | (0 << PD3) | (0 << PD1) | (0 << PD0) |
500
          (1 << PD5) | (1 << PD2);
501
502
  // enable pull ups
503
  PORTD |= (1 << PD6);
504
505
  // say hello, toggle row 1 (pixel 0,0)
506
  for (i = 0; i < 5; i++) {
507
    PORTD &= ~(1 << PD5);
508
    _delay_ms(50);
509
    PORTD |= (1 << PD5);
510
    _delay_ms(50);
511
  }
512
513
  // read last mode from eeprom
514
  // 0 mean cycle through all modes and messages
515
  mode = eeprom_read_byte(&mode_ee);
516
  if ((mode == 0) || (mode >= (MAX_ANIMATIONS + MAX_MESSAGES + 1))) {
517
    mode = 1;
518
    cycle = 1;
519
  }
520
  eeprom_write_byte(&mode_ee, mode + 1);  
521
522
  sei();
523
524
  while (1) {
525
526
    switch (mode) {
527
    case 1:
528
      break;
529
    case 2:
530
      for (i = 0; i < REPEAT_ANIMATION; i++) {
531
        copy_to_buffer(sprite_03);
532
        copy_to_display(0, 0, buffer);
533
        delay_ms(750);
534
      }
535
      break;
536
    case 3:
537
      break;
538
    default:
539
      while (message_displayed < REPEAT_TEXT) {
540
        show_char();
541
        delay_ms(TEXT_SCROLL_SPEED);
542
      }
543
      message_displayed = 0;
544
      break;
545
    }
546
547
    // cycle through all modes
548
    if (cycle) {
549
      mode++;
550
      clear_screen();
551
      if (mode >= (MAX_ANIMATIONS + MAX_MESSAGES + 1)) {
552
        mode = 1;
553
      }
554
    }
555
556
  }
557
558
  return 0;
559
560
}

von Maddin (Gast)


Lesenswert?

...Mensch Markus - du musst mal zum Ursprung referenzieren, damit man 
mal weiß wo was angeschlossen ist, dann wo du was angeschlossen hast, 
nutzt du den gleichen Prozessor, funktioniert dein Aufbau prinzipiell, 
wo hakt es.... etc.

M

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.