void OSD::update() { uint8_t *b = osdbuf; uint8_t *end_b = b+sizeof(osdbuf); PORTD &= ~_BV(PD6); // digitalWrite(MAX7456_SELECT,LOW); MAX_write(MAX7456_DMAH_reg, 0); MAX_write(MAX7456_DMAL_reg, 0); MAX_write(MAX7456_DMM_reg, 1); PORTD |= _BV(PD6); // digitalWrite(MAX7456_SELECT, HIGH); for(; b < end_b; b++) { PORTD &= ~_BV(PD6); // digitalWrite(MAX7456_SELECT, HIGH); SPDR = *b; *b=' '; // обойдемся без memset while (!(SPSR & (1<<SPIF))) ; PORTD |= _BV(PD6); // digitalWrite(MAX7456_SELECT,LOW); } PORTD &= ~_BV(PD6); // digitalWrite(MAX7456_SELECT,LOW); /CS OSD Spi.transfer(MAX7456_END_string); PORTD |= _BV(PD6); // digitalWrite(MAX7456_SELECT, HIGH); // memset(osdbuf, ' ', sizeof(osdbuf)); }
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::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::update() { uint8_t *b = osdbuf; uint8_t *end_b = b+sizeof(osdbuf); /* uint8_t bit = digitalPinToBitMask(MAX7456_SELECT); // move calculations from critical section uint8_t port = digitalPinToPort(MAX7456_SELECT); volatile uint8_t *out = portOutputRegister(port); #define SET_LOW() *out &= ~bit #define SET_HIGH() *out |= bit */ PORTD &= ~_BV(PD6); // digitalWrite(MAX7456_SELECT,LOW); MAX_write(MAX7456_DMAH_reg, 0); MAX_write(MAX7456_DMAL_reg, 0); MAX_write(MAX7456_DMM_reg, 1); // автоинкремент адреса PORTD |= _BV(PD6); // digitalWrite(MAX7456_SELECT, HIGH); for(; b < end_b; b++) { PORTD &= ~_BV(PD6); // digitalWrite(MAX7456_SELECT, HIGH); SPDR = *b; *b=' '; // обойдемся без memset while (!(SPSR & (1<<SPIF))) ; PORTD |= _BV(PD6); // digitalWrite(MAX7456_SELECT,LOW); } PORTD &= ~_BV(PD6); // digitalWrite(MAX7456_SELECT,LOW); /CS OSD Spi.transfer(MAX7456_END_string); PORTD |= _BV(PD6); // digitalWrite(MAX7456_SELECT, HIGH); }
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::control(uint8_t ctrl){ digitalWrite(MAX7456_SELECT,LOW); switch(ctrl){ case 0: MAX_write(MAX7456_VM0_reg, MAX7456_DISABLE_display | video_mode); break; case 1: MAX_write(MAX7456_VM0_reg, (MAX7456_ENABLE_display_vert | video_mode) | MAX7456_SYNC_autosync); break; } digitalWrite(MAX7456_SELECT,HIGH); }
void OSD::clear() { // clear the screen digitalWrite(MAX7456_SELECT,LOW); MAX_write(MAX7456_DMM_reg, MAX7456_CLEAR_display); digitalWrite(MAX7456_SELECT,HIGH); }
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::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(){ digitalWrite(MAX7456_SELECT,LOW); //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_HOS_reg, sets.horiz_offs); // 0x20 default // MAX_write(MAX7456_VOS_reg, sets.vert_offs); // 0x10 default setBrightness(); // define sync (auto,int,ext) and // making sure the Max7456 is enabled control(1); }
//------------------ Set Brightness --------------------------------- void OSD::setBrightness() { static const uint8_t levels[] PROGMEM = { MAX7456_WHITE_level_80, // 0 MAX7456_WHITE_level_90, // 1 MAX7456_WHITE_level_100,// 2 MAX7456_WHITE_level_120,// 3 }; uint8_t blevel = sets.OSD_BRIGHTNESS; if(blevel>3) blevel=0; blevel=levels[blevel]; // set all rows to same character white level, 90% for (byte x = 0x0, a= 0x10; x < 0x10; x++) MAX_write(a++, blevel); }
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(); } }
//------------------ Set Brightness --------------------------------- void OSD::setBrightness() { static const uint8_t levels[] PROGMEM = { MAX7456_WHITE_level_80, // 0 MAX7456_WHITE_level_90, // 1 MAX7456_WHITE_level_100,// 2 MAX7456_WHITE_level_120,// 3 }; uint8_t blevel = sets.OSD_BRIGHTNESS; if(blevel>3) blevel=0; blevel=pgm_read_byte(&levels[blevel]); Serial.printf(PSTR("\n\nSet bright to %d\n"),blevel); // set all rows to same character white level for (byte x = 0x0, a= 0x10 /* RB0 register */; x < 0x10; x++) MAX_write(a++, blevel); }
//* 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 MAX_mode(byte mode){ MAX_write(MAX7456_VM0_reg, mode); }
void OSD::clear() { // clear the screen max7456_on(); MAX_write(MAX7456_DMM_reg, MAX7456_CLEAR_display); max7456_off(); }