-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathMax7456.cpp
More file actions
250 lines (195 loc) · 5.14 KB
/
Max7456.cpp
File metadata and controls
250 lines (195 loc) · 5.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
#include "Arduino.h"
#include "KV_Team_OSD.h"
#include "Max7456.h"
// Selectable by board type
uint8_t MAX7456SELECT; // output pin
uint8_t MAX7456RESET; // output pin
// Selectable by video mode
//uint8_t ENABLE_display;
//uint8_t ENABLE_display_vert;
//uint8_t DISABLE_display;
uint16_t MAX_screen_size;
uint8_t MAX7456_reset;
uint8_t MAX_screen_rows;
volatile uint8_t vsync_wait = 0;
//////////////////////////////////////////////////////////////
uint8_t spi_transfer(uint8_t data)
{
SPDR = data; // Start the transmission
while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission
;
return SPDR; // return the received byte
}
void MAX7456_Send(uint8_t add, uint8_t data)
{
spi_transfer(add);
spi_transfer(data);
}
ISR(INT0_vect) {
vsync_wait = 0;
}
void MAX7456Configure() {
// todo - automatically recognising card.
if(Settings[S_BOARDTYPE] == 0) { // Rush
MAX7456SELECT = 10; // ss
MAX7456RESET = 9; // RESET
}
if(Settings[S_BOARDTYPE] == 1) { // MinimOSD
MAX7456SELECT = 6; // ss
MAX7456RESET = 10; // RESET
}
}
void MAX7456_Setup(void)
{
MAX7456Configure();
if(Settings[S_VIDEOSIGNALTYPE]) { // PAL
//ENABLE_display = 0x48;
//ENABLE_display_vert = 0x4c;
MAX7456_reset = 0x42;
//DISABLE_display = 0x40;
MAX_screen_size = 480;
MAX_screen_rows = 16;
}
else { // NTSC
//ENABLE_display = 0x08;
//ENABLE_display_vert = 0x0c;
MAX7456_reset = 0x02;
//DISABLE_display = 0x00;
MAX_screen_size = 390;
MAX_screen_rows = 13;
}
pinMode(MAX7456RESET,OUTPUT);
digitalWrite(MAX7456RESET,HIGH); //hard enable
#ifdef FASTINIT
delay(25);
#else
delay(250);
#endif
pinMode(MAX7456SELECT,OUTPUT);
digitalWrite(MAX7456SELECT,HIGH); //disable device
pinMode(DATAOUT, OUTPUT);
pinMode(DATAIN, INPUT);
pinMode(SPICLOCK,OUTPUT);
pinMode(VSYNC, INPUT);
// SPCR = 01010000
//interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
//sample on leading edge of clk,system clock/4 rate (4 meg)
SPCR = (1<<SPE)|(1<<MSTR);
SPSR=(1<<SPI2X);
uint8_t spi_junk;
spi_junk=SPSR;
spi_junk=SPDR;
#ifdef FASTINIT
delay(25);
#else
delay(250);
#endif
// force soft reset on Max7456
digitalWrite(MAX7456SELECT,LOW);
MAX7456_Send(VM0_reg, MAX7456_reset);
digitalWrite(MAX7456SELECT,HIGH);
#ifdef FASTINIT
delay(150);
#else
delay(500);
#endif
// set all rows to same character white level, 90%
digitalWrite(MAX7456SELECT,LOW);
uint8_t x;
for(x = 0; x < MAX_screen_rows; x++) {
MAX7456_Send(MAX7456ADD_RB0+x, WHITE_level_120);
}
// make sure the Max7456 is enabled
spi_transfer(VM0_reg);
if (Settings[S_VIDEOSIGNALTYPE]){
spi_transfer(OSD_ENABLE|VIDEO_MODE_PAL);
}
else{
spi_transfer(OSD_ENABLE|VIDEO_MODE_NTSC);
}
digitalWrite(MAX7456SELECT,HIGH);
#ifdef FASTINIT
delay(25);
#else
delay(100);
#endif
EIMSK |= (1 << INT0); // enable interuppt
EICRA |= (1 << ISC01); // interrupt at the falling edge
sei();
}
// Copy string from ram into screen buffer
void MAX7456_WriteString(const char *string, int Adresse)
{
uint8_t xx;
for(xx=0;string[xx]!=0;)
{
screen[Adresse++] = string[xx++];
}
}
// Copy string from progmem into the screen buffer
void MAX7456_WriteString_P(const char *string, int Adresse)
{
uint8_t xx = 0;
char c;
while((c = (char)pgm_read_byte(&string[xx++])) != 0)
{
screen[Adresse++] = c;
}
}
void MAX7456_writeNVM(uint8_t char_address)
{
#ifdef WRITE_TO_MAX7456
// disable display
digitalWrite(MAX7456SELECT,LOW);
spi_transfer(VM0_reg);
//spi_transfer(DISABLE_display);
//digitalWrite(MAX7456SELECT,LOW);
//spi_transfer(VM0_reg);
spi_transfer(Settings[S_VIDEOSIGNALTYPE]?0x40:0);
spi_transfer(MAX7456ADD_CMAH); // set start address high
spi_transfer(char_address);
for(uint8_t x = 0; x < NVM_ram_size; x++) // write out 54 bytes of character to shadow ram
{
spi_transfer(MAX7456ADD_CMAL); // set start address low
spi_transfer(x);
spi_transfer(MAX7456ADD_CMDI);
spi_transfer(fontData[x]);
}
// transfer 54 bytes from shadow ram to NVM
spi_transfer(MAX7456ADD_CMM);
spi_transfer(WRITE_nvr);
// wait until bit 5 in the status register returns to 0 (12ms)
while ((spi_transfer(MAX7456ADD_STAT) & STATUS_reg_nvr_busy) != 0x00);
spi_transfer(VM0_reg); // turn on screen next vertical
//spi_transfer(ENABLE_display_vert);
spi_transfer(Settings[S_VIDEOSIGNALTYPE]?0x4c:0x0c);
digitalWrite(MAX7456SELECT,HIGH);
#else
delay(12);
#endif
}
// ============================================================ WRITE TO SCREEN
void MAX7456_DrawScreen()
{
vsync_wait = 1;
while (vsync_wait)
;
int xx;
digitalWrite(MAX7456SELECT,LOW);
spi_transfer(DMM_reg);
spi_transfer(1);
spi_transfer(DMAH_reg);
spi_transfer(0);
spi_transfer(DMAL_reg);
spi_transfer(0);
for(xx=0;xx<MAX_screen_size;++xx)
{
MAX7456_Send(MAX7456ADD_DMDI, screen[xx]);
screen[xx] = ' ';
}
spi_transfer(DMDI_reg);
spi_transfer(END_string);
spi_transfer(DMM_reg);
spi_transfer(B00000000);
digitalWrite(MAX7456SELECT,HIGH);
}