void OSD::update() { uint8_t *b = osdbuf; uint8_t *end_b = b+sizeof(osdbuf); /* wee need to transfer 480 bytes, SPI speed set to 8 MHz (MAX requires min 100ns SCK period) so one byte goes in 1uS and all transfer will ends up in ~500uS */ #ifdef SLAVE_BUILD // internal Ardupilot build should use DMA to transfer max7456_on(); #else max7456_on(); MAX_write(MAX7456_DMAH_reg, 0); MAX_write(MAX7456_DMAL_reg, 0); MAX_write(MAX7456_DMM_reg, 1); // автоинкремент адреса max7456_off(); for(; b < end_b;) { max7456_on(); // strobing each byte with CS is necessary :( SPI::transfer(*b); *b++=' '; max7456_off(); } max7456_on(); SPI::transfer(MAX7456_END_string); // 0xFF - "end of screen" character #endif max7456_off(); }
void OSD::detectMode() { //read STAT and auto detect Mode PAL/NTSC max7456_on(); byte osdstat_r = MAX_read(MAX7456_STAT_reg_read);//status register if ((B00000001 & osdstat_r) != 0) { //PAL setMode(1); } else if((B00000010 & osdstat_r) != 0) { //NTSC setMode(0); } else if((B00000100 & osdstat_r) != 0) { //loss of sync // setMode(1); // PAL without video if (flags.PAL_NTSC) //NTSC setMode(0); else //PAL setMode(1); } //If no signal was detected so it uses EEPROM config else { /* if (flags.PAL_NTSC) //NTSC setMode(0); else //PAL setMode(1); */ } max7456_off(); }
void OSD::detectMode() { //read STAT and auto detect Mode PAL/NTSC max7456_on(); byte osdstat_r; if(!FLAGS.mode_auto) { goto no_auto; }else { osdstat_r = MAX_read(MAX7456_STAT_reg_read);//status register if ((B00000001 & osdstat_r) != 0){ //PAL setMode(1); FLAGS.PAL_NTSC = 1; // remember in case of camera off } else if((B00000010 & osdstat_r) != 0){ //NTSC setMode(0); FLAGS.PAL_NTSC = 0; // remember in case of camera off } else if((B00000100 & osdstat_r) != 0){ //loss of sync no_auto: if (FLAGS.PAL_NTSC) //NTSC setMode(1); else //PAL setMode(0); } } max7456_off(); }
void OSD::hw_init() { max7456_on(); //read black level register byte osdbl_r = MAX_read(MAX7456_OSDBL_reg_read);//black level read register MAX_write(MAX7456_VM0_reg, MAX7456_RESET | video_mode); delay_150(); //set black level MAX_write(MAX7456_OSDBL_reg, (osdbl_r & 0xef)); //black level write register - Set bit 4 to zero 11101111 - Enable automatic OSD black level control // set position - may be EEPROM.read(OSD_SHIFT_X) MAX_write(MAX7456_HOS_reg, 0x20); // 0x20 default MAX_write(MAX7456_VOS_reg, 0x10); // 0x10 default MAX_write(MAX7456_OSDM_reg, 0b00010010); // 0x00011011 default setBrightness(); // define sync (auto,int,ext) // MAX_write(MAX7456_VM0_reg, MAX7456_DISABLE_display | video_mode); MAX_write(MAX7456_VM0_reg, (MAX7456_ENABLE_display_vert | video_mode) | MAX7456_SYNC_internal); delay_150(); MAX_write(MAX7456_VM0_reg, (MAX7456_ENABLE_display_vert | video_mode) | MAX7456_SYNC_autosync); max7456_off(); }
void OSD::hw_init(){ max7456_on(); //read black level register byte osdbl_r = MAX_read(MAX7456_OSDBL_reg_read); //black level read register MAX_write(MAX7456_VM0_reg, MAX7456_RESET | video_mode); delay_150(); //set black level MAX_write(MAX7456_OSDBL_reg, (osdbl_r & 0xef)); //black level write register - Set bit 4 to zero 11101111 - Enable automatic OSD black level control MAX_write(MAX7456_OSDM_reg, 0b00010010); // 0x00011011 default // define sync (auto,int,ext) MAX_write(MAX7456_VM0_reg, (MAX7456_ENABLE_display_vert | video_mode) | MAX7456_SYNC_internal); // first time on internal sync delay_150(); MAX_write(MAX7456_VM0_reg, (MAX7456_ENABLE_display_vert | video_mode) | MAX7456_SYNC_autosync); // and then switch to auto mode // max7456_off(); adjust(); }
void OSD::adjust(){ max7456_on(); setBrightness(); //Serial.printf_P(PSTR("adjust bright=%d horiz=%d vert=%d\n"),sets.OSD_BRIGHTNESS,sets.horiz_offs, sets.vert_offs); MAX_write(MAX7456_HOS_reg, /* 0x20 + */ sets.horiz_offs); // 0x20 default - already shifted MAX_write(MAX7456_VOS_reg, /* 0x10 + */ sets.vert_offs); // 0x10 default max7456_off(); }
void OSD::write_NVM(uint16_t font_count, uint8_t *character_bitmap) { byte x; byte char_address_hi; byte screen_char; char_address_hi = font_count; // byte char_address_lo = 0; - autoincrement mode // cli(); - нет смысла max7456_on(); MAX_mode( MAX7456_DISABLE_display); MAX_write(MAX7456_CMAH_reg, char_address_hi);// set start address high for(x = 0; x < NVM_ram_size; x++) {// write out 54 (out of 64) bytes of character to shadow ram screen_char = *character_bitmap++; MAX_write(MAX7456_CMAL_reg, x);// set start address low MAX_write(MAX7456_CMDI_reg, screen_char); } // transfer a 54 bytes from shadow ram to NVM MAX_write(MAX7456_CMM_reg, WRITE_nvr); // wait until bit 5 in the status register returns to 0 (12ms) #if 0 while (1) { Spi.transfer(MAX7456_STAT_reg_read); if(!(Spi.transfer(0xff) & STATUS_reg_nvr_busy)) break; } #else while (1) { if(!(MAX_read(MAX7456_STAT_reg_read) & STATUS_reg_nvr_busy)) break; extern void delay_telem(); delay_telem(); // some delay } #endif MAX_mode( MAX7456_ENABLE_display_vert);// turn on screen next vertical max7456_off(); }
void OSD::setMode(uint8_t themode){ uint8_t mode; switch(themode){ case 0: mode = MAX7456_MODE_MASK_NTCS; break; default: mode = MAX7456_MODE_MASK_PAL; break; } if(video_mode != mode){ video_mode = mode; max7456_on(); MAX_mode( MAX7456_ENABLE_display_vert | video_mode | MAX7456_SYNC_autosync); max7456_off(); } }
void OSD::setMode(uint8_t themode){ uint8_t mode; switch(themode){ case 0: mode = MAX7456_MODE_MASK_NTCS; video_center = MAX7456_CENTER_NTSC; break; case 1: mode = MAX7456_MODE_MASK_PAL; video_center = MAX7456_CENTER_PAL; break; } if(video_mode != mode){ video_mode = mode; max7456_on(); MAX_write(MAX7456_VM0_reg, (MAX7456_ENABLE_display_vert | video_mode) | MAX7456_SYNC_autosync); max7456_off(); } }
//* void OSD::write_NVM(int font_count, uint8_t *character_bitmap) { byte x; byte char_address_hi; byte screen_char; char_address_hi = font_count; // byte char_address_lo = 0; // cli(); max7456_on(); MAX_write(MAX7456_VM0_reg, MAX7456_DISABLE_display); MAX_write(MAX7456_CMAH_reg, char_address_hi);// set start address high for(x = 0; x < NVM_ram_size; x++) {// write out 54 (out of 64) bytes of character to shadow ram screen_char = *character_bitmap++; MAX_write(MAX7456_CMAL_reg, x);// set start address low MAX_write(MAX7456_CMDI_reg, screen_char); } // transfer a 54 bytes from shadow ram to NVM MAX_write(MAX7456_CMM_reg, WRITE_nvr); // wait until bit 5 in the status register returns to 0 (12ms) while (1) { Spi.transfer(MAX7456_STAT_reg_read); if(!(Spi.transfer(0xff) & STATUS_reg_nvr_busy)) break; } // sei(); MAX_write(MAX7456_VM0_reg, MAX7456_ENABLE_display_vert);// turn on screen next vertical max7456_off(); }
void OSD::reset(){ max7456_on(); byte cnt=15; while(cnt-- && !( MAX_read(MAX7456_STAT_reg_read) & 0x7) ) {//read status register - sync to soft-only versions byte j=3; #ifdef SLAVE_BUILD while(j--) osd_spi->transfer(0xff); // try to sync #else while(j--) SPI::transfer(0xff); // try to sync #endif delay_15(); } MAX_mode( MAX7456_RESET | video_mode ); delay_15(); hw_init(); }
void OSD::clear() { // clear the screen max7456_on(); MAX_write(MAX7456_DMM_reg, MAX7456_CLEAR_display); max7456_off(); }