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;
    
    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::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::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::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::clear() {  // clear the screen
    max7456_on();
    MAX_write(MAX7456_DMM_reg, MAX7456_CLEAR_display);
    max7456_off();
}