Skip to content

Commit a6574c5

Browse files
Added character uploading FW
1 parent 9d6cfb7 commit a6574c5

14 files changed

+3379
-0
lines changed

Character_Updater/ArduCam_Max7456.cpp

Lines changed: 320 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,320 @@
1+
2+
#include <FastSerial.h>
3+
4+
#include "ArduCam_Max7456.h"
5+
// Get the common arduino functions
6+
#if defined(ARDUINO) && ARDUINO >= 100
7+
#include "Arduino.h"
8+
#else
9+
#include "wiring.h"
10+
#endif
11+
#include "Spi.h"
12+
#include <EEPROM.h>
13+
#include "OSD_Config.h"
14+
15+
volatile int16_t x;
16+
volatile int font_count;
17+
volatile byte character_bitmap[0x40];
18+
19+
OSD::OSD()
20+
{
21+
}
22+
23+
//------------------ init ---------------------------------------------------
24+
25+
void OSD::init()
26+
{
27+
pinMode(MAX7456_SELECT,OUTPUT);
28+
pinMode(MAX7456_VSYNC, INPUT);
29+
digitalWrite(MAX7456_VSYNC,HIGH); //enabling pull-up resistor
30+
31+
detectMode();
32+
33+
digitalWrite(MAX7456_SELECT,LOW);
34+
//read black level register
35+
Spi.transfer(MAX7456_OSDBL_reg_read);//black level read register
36+
byte osdbl_r = Spi.transfer(0xff);
37+
Spi.transfer(MAX7456_VM0_reg);
38+
Spi.transfer(MAX7456_RESET | video_mode);
39+
delay(50);
40+
//set black level
41+
byte osdbl_w = (osdbl_r & 0xef); //Set bit 4 to zero 11101111
42+
Spi.transfer(MAX7456_OSDBL_reg); //black level write register
43+
Spi.transfer(osdbl_w);
44+
45+
setBrightness();
46+
// define sync (auto,int,ext) and
47+
// making sure the Max7456 is enabled
48+
control(1);
49+
}
50+
51+
//------------------ Detect Mode (PAL/NTSC) ---------------------------------
52+
53+
void OSD::detectMode()
54+
{
55+
//read STAT and auto detect Mode PAL/NTSC
56+
digitalWrite(MAX7456_SELECT,LOW);
57+
Spi.transfer(MAX7456_STAT_reg_read);//status register
58+
byte osdstat_r = Spi.transfer(0xff);
59+
60+
if ((B00000001 & osdstat_r) == 1){ //PAL
61+
setMode(1);
62+
}
63+
else if((B00000010 & osdstat_r) == 1){ //NTSC
64+
setMode(0);
65+
}
66+
//If no signal was detected so it uses EEPROM config
67+
else{
68+
if (EEPROM.read(PAL_NTSC_ADDR) == 0){ //NTSC
69+
setMode(0);
70+
}
71+
else { //PAL
72+
setMode(1);
73+
}
74+
digitalWrite(MAX7456_SELECT,LOW);
75+
}
76+
}
77+
78+
//------------------ Set Brightness ---------------------------------
79+
void OSD::setBrightness()
80+
{
81+
82+
uint8_t blevel = EEPROM.read(OSD_BRIGHTNESS_ADDR);
83+
84+
if(blevel == 0) //low brightness
85+
blevel = MAX7456_WHITE_level_80;
86+
else if(blevel == 1)
87+
blevel = MAX7456_WHITE_level_90;
88+
else if(blevel == 2)
89+
blevel = MAX7456_WHITE_level_100;
90+
else if(blevel == 3) //high brightness
91+
blevel = MAX7456_WHITE_level_120;
92+
else
93+
blevel = MAX7456_WHITE_level_80; //low brightness if bad value
94+
95+
// set all rows to same charactor white level, 90%
96+
for (x = 0x0; x < 0x10; x++)
97+
{
98+
Spi.transfer(x + 0x10);
99+
Spi.transfer(blevel);
100+
}
101+
}
102+
103+
//------------------ Set Mode (PAL/NTSC) ------------------------------------
104+
105+
void OSD::setMode(int themode)
106+
{
107+
switch(themode){
108+
case 0:
109+
video_mode = MAX7456_MODE_MASK_NTCS;
110+
video_center = MAX7456_CENTER_NTSC;
111+
break;
112+
case 1:
113+
video_mode = MAX7456_MODE_MASK_PAL;
114+
video_center = MAX7456_CENTER_PAL;
115+
break;
116+
}
117+
}
118+
119+
//------------------ Get Mode (PAL 0/NTSC 1) --------------------------------
120+
121+
int OSD::getMode()
122+
{
123+
switch(video_mode){
124+
case MAX7456_MODE_MASK_NTCS:
125+
return 0;
126+
break;
127+
case MAX7456_MODE_MASK_PAL:
128+
return 1;
129+
break;
130+
}
131+
return 0;
132+
}
133+
134+
//------------------ Get Center (PAL/NTSC) ----------------------------------
135+
136+
int OSD::getCenter()
137+
{
138+
return video_center; //first line for center panel
139+
}
140+
141+
//------------------ plug ---------------------------------------------------
142+
143+
void OSD::plug()
144+
{
145+
digitalWrite(MAX7456_SELECT,LOW);
146+
}
147+
148+
//------------------ clear ---------------------------------------------------
149+
150+
void OSD::clear()
151+
{
152+
// clear the screen
153+
digitalWrite(MAX7456_SELECT,LOW);
154+
Spi.transfer(MAX7456_DMM_reg);
155+
Spi.transfer(MAX7456_CLEAR_display);
156+
digitalWrite(MAX7456_SELECT,HIGH);
157+
}
158+
159+
//------------------ set panel -----------------------------------------------
160+
161+
void
162+
OSD::setPanel(uint8_t st_col, uint8_t st_row){
163+
start_col = st_col;
164+
start_row = st_row;
165+
col = st_col;
166+
row = st_row;
167+
}
168+
169+
//------------------ open panel ----------------------------------------------
170+
171+
void
172+
OSD::openPanel(void){
173+
unsigned int linepos;
174+
byte settings, char_address_hi, char_address_lo;
175+
176+
//find [start address] position
177+
linepos = row*30+col;
178+
179+
// divide 16 bits into hi & lo byte
180+
char_address_hi = linepos >> 8;
181+
char_address_lo = linepos;
182+
183+
//Auto increment turn writing fast (less SPI commands).
184+
//No need to set next char address. Just send them
185+
settings = MAX7456_INCREMENT_auto; //To Enable DMM Auto Increment
186+
digitalWrite(MAX7456_SELECT,LOW);
187+
Spi.transfer(MAX7456_DMM_reg); //dmm
188+
Spi.transfer(settings);
189+
190+
Spi.transfer(MAX7456_DMAH_reg); // set start address high
191+
Spi.transfer(char_address_hi);
192+
193+
Spi.transfer(MAX7456_DMAL_reg); // set start address low
194+
Spi.transfer(char_address_lo);
195+
//Serial.printf("setPos -> %d %d\n", col, row);
196+
}
197+
198+
//------------------ close panel ---------------------------------------------
199+
200+
void
201+
OSD::closePanel(void){
202+
Spi.transfer(MAX7456_DMDI_reg);
203+
Spi.transfer(MAX7456_END_string); //This is needed "trick" to finish auto increment
204+
digitalWrite(MAX7456_SELECT,HIGH);
205+
//Serial.println("close");
206+
row++; //only after finish the auto increment the new row will really act as desired
207+
}
208+
209+
//------------------ write single char ---------------------------------------------
210+
211+
void
212+
OSD::openSingle(uint8_t x, uint8_t y){
213+
unsigned int linepos;
214+
byte char_address_hi, char_address_lo;
215+
216+
//find [start address] position
217+
linepos = y*30+x;
218+
219+
// divide 16 bits into hi & lo byte
220+
char_address_hi = linepos >> 8;
221+
char_address_lo = linepos;
222+
223+
digitalWrite(MAX7456_SELECT,LOW);
224+
225+
Spi.transfer(MAX7456_DMAH_reg); // set start address high
226+
Spi.transfer(char_address_hi);
227+
228+
Spi.transfer(MAX7456_DMAL_reg); // set start address low
229+
Spi.transfer(char_address_lo);
230+
//Serial.printf("setPos -> %d %d\n", col, row);
231+
}
232+
233+
//------------------ write ---------------------------------------------------
234+
235+
size_t
236+
OSD::write(uint8_t c){
237+
if(c == '|'){
238+
closePanel(); //It does all needed to finish auto increment and change current row
239+
openPanel(); //It does all needed to re-enable auto increment
240+
}
241+
else{
242+
Spi.transfer(MAX7456_DMDI_reg);
243+
Spi.transfer(c);
244+
}
245+
return 1;
246+
}
247+
248+
//---------------------------------
249+
250+
void
251+
OSD::control(uint8_t ctrl){
252+
digitalWrite(MAX7456_SELECT,LOW);
253+
Spi.transfer(MAX7456_VM0_reg);
254+
switch(ctrl){
255+
case 0:
256+
Spi.transfer(MAX7456_DISABLE_display | video_mode);
257+
break;
258+
case 1:
259+
//Spi.transfer((MAX7456_ENABLE_display_vert | video_mode) | MAX7456_SYNC_internal);
260+
//Spi.transfer((MAX7456_ENABLE_display_vert | video_mode) | MAX7456_SYNC_external);
261+
Spi.transfer((MAX7456_ENABLE_display_vert | video_mode) | MAX7456_SYNC_autosync);
262+
break;
263+
}
264+
digitalWrite(MAX7456_SELECT,HIGH);
265+
}
266+
267+
void
268+
OSD::write_NVM(int font_count, uint8_t *character_bitmap)
269+
{
270+
byte x;
271+
byte char_address_hi, char_address_lo;
272+
byte screen_char;
273+
274+
char_address_hi = font_count;
275+
char_address_lo = 0;
276+
//Serial.println("write_new_screen");
277+
278+
// disable display
279+
digitalWrite(MAX7456_SELECT,LOW);
280+
Spi.transfer(MAX7456_VM0_reg);
281+
Spi.transfer(MAX7456_DISABLE_display);
282+
283+
Spi.transfer(MAX7456_CMAH_reg); // set start address high
284+
Spi.transfer(char_address_hi);
285+
286+
for(x = 0; x < NVM_ram_size; x++) // write out 54 (out of 64) bytes of character to shadow ram
287+
{
288+
screen_char = character_bitmap[x];
289+
Spi.transfer(MAX7456_CMAL_reg); // set start address low
290+
Spi.transfer(x);
291+
Spi.transfer(MAX7456_CMDI_reg);
292+
Spi.transfer(screen_char);
293+
}
294+
295+
// transfer a 54 bytes from shadow ram to NVM
296+
Spi.transfer(MAX7456_CMM_reg);
297+
Spi.transfer(WRITE_nvr);
298+
299+
// wait until bit 5 in the status register returns to 0 (12ms)
300+
while ((Spi.transfer(MAX7456_STAT_reg_read) & STATUS_reg_nvr_busy) != 0x00);
301+
302+
Spi.transfer(MAX7456_VM0_reg); // turn on screen next vertical
303+
Spi.transfer(MAX7456_ENABLE_display_vert);
304+
digitalWrite(MAX7456_SELECT,HIGH);
305+
}
306+
307+
//------------------ pure virtual ones (just overriding) ---------------------
308+
309+
int OSD::available(void){
310+
return 0;
311+
}
312+
int OSD::read(void){
313+
return 0;
314+
}
315+
int OSD::peek(void){
316+
return 0;
317+
}
318+
void OSD::flush(void){
319+
}
320+

0 commit comments

Comments
 (0)