Um die Daten von einem DataFlash möglichst effizient in ein Display zu
bekommen, hatte ich das mal folgendermassen gemacht:
1 | void display_sprite(uint16_t page, uint16_t byte, uint8_t x, uint8_t y, uint8_t w, uint8_t h) {
|
2 | speed_inc();
|
3 |
|
4 | mem_init_read(page, byte, 12);
|
5 |
|
6 | display_cmd((uint8_t *)0xef90, 0);
|
7 | display_cmd((uint8_t *)0x0500, 0);
|
8 | display_cmd((uint8_t *)(0x0800 | x), 0);
|
9 | display_cmd((uint8_t *)(0x0900 | (x + w - 1)), 0);
|
10 | display_cmd((uint8_t *)(0x0a00 | y), 0);
|
11 | display_cmd((uint8_t *)(0x0b00 | (y + h - 1)), 0);
|
12 |
|
13 | SPDR = 0xff;
|
14 | loop_until_bit_is_set(SPSR, SPIF);
|
15 | RPO_D_RS &= ~_BV(PIN_D_RS);
|
16 | for (uint16_t i = 0; i < w * h; ++i) {
|
17 | loop_until_bit_is_set(SPSR, SPIF);
|
18 | SPDR = SPDR;
|
19 | loop_until_bit_is_set(SPSR, SPIF);
|
20 | SPDR = SPDR;
|
21 | }
|
22 |
|
23 | loop_until_bit_is_set(SPSR, SPIF);
|
24 |
|
25 | RPO_MEM_CS |= _BV(PIN_MEM_CS);
|
26 | RPO_D_CS |= _BV(PIN_D_CS);
|
27 |
|
28 | speed_dec();
|
29 | }
|
30 |
|
31 | void mem_init_read(uint16_t page, uint16_t byte, uint8_t offset) {
|
32 | RPO_MEM_CS &= ~_BV(PIN_MEM_CS);
|
33 | RPO_D_CS |= _BV(PIN_D_CS);
|
34 |
|
35 | if (offset <= 4) {
|
36 | offset = 4 - offset;
|
37 | } else {
|
38 | if (byte < offset - 4) {
|
39 | page = (page - 1) & MEM_LASTPAGE;
|
40 | byte = 264 - (offset - 4) + byte;
|
41 | } else {
|
42 | byte -= (offset - 4);
|
43 | }
|
44 | offset = 0;
|
45 | }
|
46 |
|
47 | SPDR = MEM_OP_CONTREAD;
|
48 | loop_until_bit_is_set(SPSR, SPIF);
|
49 | SPDR = H8(page << 1);
|
50 | loop_until_bit_is_set(SPSR, SPIF);
|
51 | SPDR = L8(page) << 1 | H8(byte);
|
52 | loop_until_bit_is_set(SPSR, SPIF);
|
53 | SPDR = L8(byte);
|
54 | loop_until_bit_is_set(SPSR, SPIF);
|
55 |
|
56 | for (; offset; --offset) {
|
57 | SPDR = 0xff;
|
58 | loop_until_bit_is_set(SPSR, SPIF);
|
59 | }
|
60 | }
|
mem_init_read() initialisiert den Speicher, damit anschliessend alle
Daten am Stück gelesen werden (Pro Taktzyklus ein Bit, keine Wartezeiten
o.Ä. bei Pagegrenzen). Danach wird das Display entsprechend
initialisiert, wobei aber darauf geachtet werden muss, dass bei diesem
Vorgang Daten auch zum Speicher gelangen. Das ist nicht weiter tragisch,
erzeugt jedoch einen Datenoffset, da bei jedem Kommando an's Display
ein, bzw. zwei Bytes aus dem Speicher gelesen werden. Daher ist
mem_init_read() auch mit etwas komischer Rechnerei versehen.
Anschliessend wird in einer Schleife jedes Byte vom Speicher gelesen und
mit dem gleichen (!) Takt das vorhergehende Byte an's Display gesendet.