Не компилируется скетч

rezak.69
Offline
Зарегистрирован: 23.03.2019

Добрый вечер ВСЕМ! Проблема со скетчем ,он с буржуйского сайта - это часы VLD(ВЛИ) постоянная ошибка в одном и том же месте, библиотеки все на месте все обновил , но ошибка никуда не делась.

/*
* TC18 by Jason von Nieda <jason@vonnieda.org>
* License: CC BY-SA
* 
* Board Configuration
*  Arduino Duemilanove or Diecimila, ATmega328P or ATmega168 @ 16MHz
*  Arduino will set the brown out detect too high on burning the bootloader
*  so it has to be changed to 1.8 manually.
*  VBB feedback       Analog 0 (PC0)
*    VBB with 100k to 1k voltage divider
*  SCK to MAX6921     Digital 13 (PB5)
*  MOSI to MAX6921    Digital 11 (PB3)
*  PPS                Digital 8 (PB0)
*  SW2 (ENC_B)        Digital 7 (PD7)
*  SW1 (ENC_A)        Digital 6 (PD6)
*  SW3 (ENC_SW)       Digital 5 (PD5)
*  LOAD               Digital 4 (PD4)
*  BOOST              Digital 3 (PD3)
*  SDA                Analog 4 (PC4)
*  SCL                Analog 5 (PC5)
*  RXD                Digital 0 (PD0)
*  TXD                Digital 1 (PD1)
*/

#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdio.h>
#include <Wire.h>
#include <EEPROM.h>

#define DS3231_ADDR   0b01101000

#define VFDLOAD_DDR   DDRD
#define VFDLOAD_PORT  PORTD
#define VFDLOAD       PORTD4

#define BOOST_DDR     DDRD
#define BOOST_PORT    PORTD
#define BOOST         PORTD3

#define PPS_DDR       DDRB
#define PPS_PIN       PINB
#define PPS           PORTB0

#define ENC_A_DDR     DDRD
#define ENC_A_PIN     PIND
#define ENC_A_PORT    PORTD
#define ENC_A         PORTD6

#define ENC_B_DDR     DDRD
#define ENC_B_PIN     PIND
#define ENC_B_PORT    PORTD
#define ENC_B         PORTD7

#define ENC_SW_DDR    DDRD
#define ENC_SW_PIN    PIND
#define ENC_SW_PORT   PORTD
#define ENC_SW        PORTD5

#define VFD_SEG_A     0b00000001
#define VFD_SEG_B     0b00000010
#define VFD_SEG_C     0b00000100
#define VFD_SEG_D     0b00001000
#define VFD_SEG_E     0b00010000
#define VFD_SEG_F     0b00100000
#define VFD_SEG_G     0b01000000
#define VFD_SEG_H     0b10000000

#define VFD_DIGIT_0   0b000000001
#define VFD_DIGIT_1   0b000000010
#define VFD_DIGIT_2   0b000000100
#define VFD_DIGIT_3   0b000001000
#define VFD_DIGIT_4   0b000010000
#define VFD_DIGIT_5   0b000100000
#define VFD_DIGIT_6   0b001000000
#define VFD_DIGIT_7   0b010000000
#define VFD_DIGIT_8   0b100000000

#define MENU_TIMEOUT  10000

static const byte vfd_font[] = {
  /* 0 - 9 */
  VFD_SEG_A | VFD_SEG_B | VFD_SEG_C | VFD_SEG_D | VFD_SEG_E | VFD_SEG_F,
  VFD_SEG_B | VFD_SEG_C,
  VFD_SEG_A | VFD_SEG_B | VFD_SEG_D | VFD_SEG_E | VFD_SEG_G,
  VFD_SEG_A | VFD_SEG_B | VFD_SEG_C | VFD_SEG_D | VFD_SEG_G,
  VFD_SEG_B | VFD_SEG_C | VFD_SEG_F | VFD_SEG_G,
  VFD_SEG_A | VFD_SEG_C | VFD_SEG_D | VFD_SEG_F | VFD_SEG_G,
  VFD_SEG_A | VFD_SEG_C | VFD_SEG_D | VFD_SEG_E | VFD_SEG_F | VFD_SEG_G,
  VFD_SEG_A | VFD_SEG_B | VFD_SEG_C,
  VFD_SEG_A | VFD_SEG_B | VFD_SEG_C | VFD_SEG_D | VFD_SEG_E | VFD_SEG_F | VFD_SEG_G,
  VFD_SEG_A | VFD_SEG_B | VFD_SEG_C | VFD_SEG_F | VFD_SEG_G,
  
  /* a - z */
  VFD_SEG_A | VFD_SEG_B | VFD_SEG_C | VFD_SEG_D | VFD_SEG_E | VFD_SEG_G,
  VFD_SEG_C | VFD_SEG_D | VFD_SEG_E | VFD_SEG_F | VFD_SEG_G,
  VFD_SEG_D | VFD_SEG_E | VFD_SEG_G,
  VFD_SEG_B | VFD_SEG_C | VFD_SEG_D | VFD_SEG_E | VFD_SEG_G,
  VFD_SEG_A | VFD_SEG_B | VFD_SEG_D | VFD_SEG_E | VFD_SEG_F | VFD_SEG_G,
  VFD_SEG_A | VFD_SEG_E | VFD_SEG_F | VFD_SEG_G,
  VFD_SEG_A | VFD_SEG_B | VFD_SEG_C | VFD_SEG_D | VFD_SEG_F | VFD_SEG_G,
  VFD_SEG_C | VFD_SEG_E | VFD_SEG_F | VFD_SEG_G,
  VFD_SEG_B | VFD_SEG_C,
  VFD_SEG_B | VFD_SEG_C | VFD_SEG_D | VFD_SEG_E,
  VFD_SEG_A | VFD_SEG_C | VFD_SEG_E | VFD_SEG_F | VFD_SEG_G,
  VFD_SEG_D | VFD_SEG_E | VFD_SEG_F,
  VFD_SEG_A | VFD_SEG_C | VFD_SEG_E | VFD_SEG_G,
  VFD_SEG_C | VFD_SEG_E | VFD_SEG_G,
  VFD_SEG_C | VFD_SEG_D | VFD_SEG_E | VFD_SEG_G,
  VFD_SEG_A | VFD_SEG_B | VFD_SEG_E | VFD_SEG_F | VFD_SEG_G,
  VFD_SEG_A | VFD_SEG_B | VFD_SEG_C | VFD_SEG_D | VFD_SEG_G | VFD_SEG_H,
  VFD_SEG_E | VFD_SEG_G,
  VFD_SEG_A | VFD_SEG_C | VFD_SEG_D | VFD_SEG_F | VFD_SEG_G,
  VFD_SEG_D | VFD_SEG_E | VFD_SEG_F | VFD_SEG_G,
  VFD_SEG_C | VFD_SEG_D | VFD_SEG_E,
  VFD_SEG_C | VFD_SEG_D | VFD_SEG_E,
  VFD_SEG_A | VFD_SEG_C | VFD_SEG_D | VFD_SEG_E,
  VFD_SEG_B | VFD_SEG_C | VFD_SEG_E | VFD_SEG_F | VFD_SEG_G,
  VFD_SEG_B | VFD_SEG_C | VFD_SEG_D | VFD_SEG_F | VFD_SEG_G,
  VFD_SEG_A | VFD_SEG_B | VFD_SEG_D | VFD_SEG_E | VFD_SEG_G,
};

static const char *month_abbrevs[] = {
  "Jan",
  "Feb",
  "Mar",
  "Apr",
  "May",
  "Jun",
  "Jul",
  "Aug",
  "Sep",
  "Oct",
  "Nov",
  "Dec",
};

volatile byte vfd_data[9];
volatile byte vfd_digit;
// Digit dwell is used to adjust the brightness of individual digits on
// the display. Used to compensate for tube manufacturing differences.
// Increasing the value of a position causes the refresh loop to dwell on
// that digit for additional cycles causing it's brightness to increase.
// Use sparingly. This slows the refresh of the entire display.
// This feature is not yet complete. Needs to be moved to a configuration
// menu and stored in config.
byte vfd_digit_dwell[] = {
  0, 0, 0, 0, 0, 0, 0, 0, 1
};
volatile byte vfd_digit_dwell_count;
volatile unsigned long spi_buffer;
volatile byte spi_buffer_count;

// Default boost voltage used during startup, this is quickly replaced by the
// config data
float voltage_target = 30.00;
// The allowable voltage +/- drift before the ADC interrupt makes adjustements
static const float voltage_drift = 3.00;
// The current voltage as measured by the ADC
float voltage;
// The number of times the voltage has been sampled. This is used to limit
// the frequency of updates to the boost PWM.
byte voltage_sample;

volatile char encoder_debounce = -1;
volatile char encoder_pos;
volatile char encoder_pressed;

volatile byte hour, minute, second, year, month, date;
volatile unsigned int millisecond;
volatile float temperature;

// Used in many main loop functions to format text for display
char display_buf[20];

// Configurable options, pulled from EEPROM at startup and stored
// when changed.
char display_mode;
char brightness;
char bank_mode;

void setup() {
  Serial.begin(9600);
  
  BOOST_DDR |= _BV(BOOST);

  // Timer 2 is used to create the waveform for the boost controller
  // Timer 2 Waveform Generation Mode 3 Fast PWM
  // Compare Output Mode Clear OC2B on Compare Match, set OC2B at BOTTOM
  TCCR2A = _BV(WGM21) | _BV(WGM20) | _BV(COM2B1);
  // Clock Select No Prescaling
  TCCR2B = _BV(CS20);
  // Initial value for boost timer
  OCR2B = 230;
  
  // Timer 1 is used to refresh the VFD display
  // Set defaults in case Arduino screws them up
  TCCR1A = 0;
  // Clock Select No Prescaling
  TCCR1B = _BV(CS10);
  // Interrupt Enable
  TIMSK1 = _BV(TOIE1);
  
  // Internal 1.1V Voltage Reference, Single Ended Input on ADC0
  ADMUX = _BV(REFS1) | _BV(REFS0);
  // ADC Enable, ADC Auto Trigger Enable, ADC Interrupt Enable
  // ADC Prescaler 128
  ADCSRA |= _BV(ADEN) | _BV(ADATE) | _BV(ADIE) 
    | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0);
  // ADC Start Conversion (starts free running mode)
  ADCSRA |= _BV(ADSC);
  
  // Enable SS, MOSI and SCK as outputs, required by SPI
  DDRB |= _BV(PORTB2) | _BV(PORTB3) | _BV(PORTB5);
  // SPI Enable, Master Mode, Interrupt Enable, FOSC/16
  SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR0) | _BV(SPIE);
 
  VFDLOAD_DDR |= _BV(VFDLOAD);
  
  // Enable Pin Change Interrupt 0 PCINT0 (PB0) [PPS]
  PCICR |= _BV(PCIE0);
  PCMSK0 |= _BV(PCINT0);
  
  // Set ENC_A, ENC_B and ENC_SW pins to input
  ENC_A_DDR &= ~(_BV(ENC_A));
  ENC_B_DDR &= ~(_BV(ENC_B));
  ENC_SW_DDR &= ~(_BV(ENC_SW));
  
  // Turn on internal pullups for ENC_A, ENC_B, ENC_SW
  ENC_A_PORT |= _BV(ENC_A);
  ENC_B_PORT |= _BV(ENC_B);
  ENC_SW_PORT |= _BV(ENC_SW);
  
  // Enable Pin Change Interrupt 2 for PCINT22 (PD6) [ENC_A], PCINT21 (PD5) [ENC_SW]
  PCMSK2 |= _BV(PCINT21);
  PCMSK2 |= _BV(PCINT22);
  PCICR |= _BV(PCIE2);
  
  ds3231_setup();
  
  load_config();
}

void ds3231_setup() {
  Wire.begin();
  // set the control register
  ds3231_set_register(0x0e, 0b00000000);
}

byte dec_to_bcd(int dec) {
  return ((dec % 10) | ((dec / 10) << 4));
}

int bcd_to_dec(byte bcd) {
  return (((bcd >> 4) * 10) + (bcd & 0x0f));
}

void ds3231_set_register(byte address, byte value) {
  Wire.beginTransmission(DS3231_ADDR);
  Wire.send(address);
  Wire.send(value);
  Wire.endTransmission();
}

byte ds3231_get_register(byte address) {
  Wire.beginTransmission(DS3231_ADDR);
  Wire.send(address);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_ADDR, 1);
  while (Wire.available() < 1);
  return Wire.receive();
}

void ds3231_set_time(byte hour, byte minute, byte second) {
  Wire.beginTransmission(DS3231_ADDR);
  Wire.send(0x00);
  Wire.send(dec_to_bcd(second));
  Wire.send(dec_to_bcd(minute));
  Wire.send(dec_to_bcd(hour));
  Wire.endTransmission();
}

void ds3231_get_time(byte *hour, byte *minute, byte *second) {
  Wire.beginTransmission(DS3231_ADDR);
  Wire.send(0x00);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_ADDR, 3);
  while (Wire.available() < 3);
  byte s = Wire.receive();
  byte m = Wire.receive();
  byte h = Wire.receive();
  *second = bcd_to_dec(s);
  *minute = bcd_to_dec(m);
  *hour = bcd_to_dec(h);
}

void ds3231_set_date(byte year, byte month, byte date) {
  Wire.beginTransmission(DS3231_ADDR);
  Wire.send(0x04);
  Wire.send(dec_to_bcd(date));
  Wire.send(dec_to_bcd(month));
  Wire.send(dec_to_bcd(year));
  Wire.endTransmission();
}

void ds3231_get_date(byte *year, byte *month, byte *date) {
  Wire.beginTransmission(DS3231_ADDR);
  Wire.send(0x04);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_ADDR, 3);
  while (Wire.available() < 3);
  byte d = Wire.receive();
  byte m = Wire.receive();
  byte y = Wire.receive();
  *date = bcd_to_dec(d);
  *month = bcd_to_dec(m & 0b00011111);
  *year = bcd_to_dec(y);
}

float ds3231_get_temp() {
  byte msb = ds3231_get_register(0x11);
  byte lsb = ds3231_get_register(0x12);
  float c = msb + ((lsb >> 6) * 0.25f);
  return c;
}

/*
  Load the given VFD data into the SPI buffer and start the transfer.
  This sends the first byte of the data. The rest is sent from the
  SPI interrupt.
*/
static inline void vfd_send(unsigned long d) {
  spi_buffer = d << 8;
  spi_buffer_count = 3;
  
  SPDR = (spi_buffer >> 24);
  spi_buffer <<= 8;
  spi_buffer_count--;
}

/*
  Refresh the VFD by showing the next digit
*/
static inline void vfd_refresh() {
  if (vfd_digit_dwell_count--) {
    return;
  }
  vfd_digit_dwell_count = vfd_digit_dwell[8 - vfd_digit];
  uint32_t d = vfd_data[8 - vfd_digit];
  d <<= 9;
  d |= (1 << vfd_digit);
  vfd_send(d);
  vfd_digit++;
  if (vfd_digit > 8) {
    vfd_digit = 0;
  }
}
  
/*
  Map the given char to the correct VFD segment byte
  using the font table and some internals.
   a
 f   b  
   g  
 e   c   
   d
       h   
*/
byte vfd_map_char(char c) {
  if (c >= 'a' && c <= 'z') {
    return vfd_font[c - 'a' + 10]; 
  }
  else if (c >= 'A' && c <= 'Z') {
    return vfd_font[c - 'A' + 10];
  }
  else if (c >= '0' && c <= '9') {
    return vfd_font[c - '0']; 
  }
  else if (c == ' ') {
    return 0; 
  }
  else if (c == '-') {
    return VFD_SEG_G;
  }
  else if (c == '.') {
    return VFD_SEG_H;
  }
  else if (c == '!') {
    return VFD_SEG_B | VFD_SEG_C | VFD_SEG_H;
  }
  else if (c == '?') {
    return VFD_SEG_A | VFD_SEG_B | VFD_SEG_E | VFD_SEG_G | VFD_SEG_H;
  }
  else if (c == ',') {
    return VFD_SEG_C;
  }
  else if (c == -1) {
    return VFD_SEG_G | VFD_SEG_H;
  }
  else {
    return 0; 
  }
}

/*
  Print the given string to the VFD
*/
void vfd_set_string(char *s, int offset) {
  int slen = strlen(s);
  
  for (int i = offset; i < offset + 8; i++) {
    if (i < 0 || i > slen - 1) {
      vfd_data[i - offset + 1] = 0;
    }
    else {
      vfd_data[i - offset + 1] = vfd_map_char(s[i]);
    }
  }
}

void vfd_scroll_string(char *s, int del) {
  int slen = strlen(s);
  for (int i = -7; i < slen; i++) {
    vfd_set_string(s, i);
    delay(del);
  }
}

int serial_readline(char *s, int length) {
  int ch;
  do {
    ch = Serial.read();
    *s++ = ch;
  } while (ch != '\n' && ch != '\r' && Serial.available() > 0);
  *s = NULL;
  return 0;
}

/*
  Handles the ADC conversion complete interrupt. ADC is used to
  measure the output of the voltage boost circuit and adjusts it
  to stay near the target voltage by adjusting the PWM width
  going to the boost MOSFET.
*/
ISR(ADC_vect) {
  byte low = ADCL;
  byte high = ADCH;
  if (voltage_sample++ > 20) {
    voltage_sample = 0;
    int adc = (high << 8) | low;
    voltage = 1.066f / (0x3ff - 1) * adc * 112.344;
    // We don't let the boost generator go below 10 or above 230
    // Those equate to roughly VCC and 60v so allowing it to
    // go too high can start blowing up components.
    if (voltage > voltage_target + voltage_drift && OCR2B > 10) {
      OCR2B--;
    }
    else if (voltage < voltage_target - voltage_drift && OCR2B < 230) {
      OCR2B++;
    }
  }
}

/*
  Timer fires approx. every 1ms and handles refreshing the VFD,
  debouncing inputs and updating the milliscond time register.
*/
ISR(TIMER1_OVF_vect) {
  // fire approx every 1ms
  TCNT1 = 0xffff - 16000;
  
  millisecond++;
  
  if (encoder_debounce >= 0) {
    encoder_debounce--;
  }
  
  if (encoder_debounce == 0) {
    int encoder_a = (ENC_A_PIN & _BV(ENC_A));
    int encoder_b = (ENC_B_PIN & _BV(ENC_B));
    int encoder_sw = (ENC_SW_PIN & _BV(ENC_SW));
    
    if (!encoder_sw) {
      encoder_pressed++;
    }
    
    if (!encoder_a) {
      encoder_pos += encoder_b ? -1 : +1;
    }
    PCIFR |= _BV(PCIF2);
    PCICR |= _BV(PCIE2);
  }
  
  vfd_refresh();
}

/*
  Picks up interrupts from any of the encoder pins changing and
  starts the debounce procedure. 
*/
ISR(PCINT2_vect) {
  encoder_debounce = 2;
  PCICR &= ~(_BV(PCIE2));
  PCIFR |= _BV(PCIF2);
}

/*
  Handles interrupts from the PPS (pulse per second) interrupt
  updating all the time registers
*/
ISR(PCINT0_vect) {
  if (PPS_PIN & _BV(PPS)) {
    // we have to enable interrupts because the Wire library uses them
    sei();
    ds3231_get_time((byte *) &hour, (byte *) &minute, (byte *) &second);
    ds3231_get_date((byte *) &year, (byte *) &month, (byte *) &date);
    temperature = ds3231_get_temp();
    millisecond = 0;
  }
}

/*
  Handles the completion of a SPI transfer and either latches
  the data or starts the transfer of the next byte
*/
ISR(SPI_STC_vect) {
  if (spi_buffer_count) {
    SPDR = (spi_buffer >> 24);
    spi_buffer <<= 8;
    spi_buffer_count--;
  }
  else {
    // latch data
    VFDLOAD_PORT |= _BV(VFDLOAD);
    VFDLOAD_PORT &= ~_BV(VFDLOAD);
  }
}

/*
  Wait the given number of milliseconds (ms) for any input from the encoder.
  If there is input the enc_moved and enc_pressed references are filled in
  and the function returns true. If no input is detected before the
  timer expires the function returns false.
  This function clears the global input counters in either case.
*/
boolean wait_for_input(int ms, char *enc_pos, boolean *enc_pressed) {
  unsigned long m = millis() + ms;
  while (!encoder_pressed && !encoder_pos && (millis() < m));
  *enc_pos = encoder_pos;
  *enc_pressed = encoder_pressed;
  encoder_pressed = 0;
  encoder_pos = 0;
  return *enc_pressed || *enc_pos;
}

void load_config() {
  byte b;

  b = EEPROM.read(0);
  if (b == 255) {
    b = 0;
  }
  display_mode = b;
  
  b = EEPROM.read(1);
  if (b == 255) {
    b = 2;
  }
  brightness = b;
  voltage_target = 20.0 + ((brightness + 1) * 3.75);
  
  b = EEPROM.read(2);
  if (b == 255) {
    b = 1;
  }
  bank_mode = b;
  
}

void save_config() {
  EEPROM.write(0, display_mode);
  EEPROM.write(1, brightness);
  EEPROM.write(2, bank_mode);
}

/*
  In setting the time we will display the current time with first the hours, then minutes, then seconds
  flashing once per second. The encoder turning increments or decrements the currently flashing item
  and encoder button causes the next item to become flashing. A push with seconds flashing returns.
*/
void set_time() {
  int h = hour, m = minute, s = second;
  
  char enc_pos = 0;
  boolean enc_pressed = 0;
  
  boolean flash = false;
  
  int hms_current = 0;
  int *hms[] = {
    &h,
    &m,
    &s
  };

  while (1) {
    for (int i = 0; i < 3; i++) {
      if (i == hms_current && flash) {
        sprintf(display_buf + (i * 3), "  :");
      }
      else {
        sprintf(display_buf + (i * 3), "%02d:", *hms[i]);
      }
    }
    
    vfd_set_string(display_buf, 0);

    if (wait_for_input(500, &enc_pos, &enc_pressed)) {
      if (enc_pressed) {
        hms_current++;
        if (hms_current > 2) {
          ds3231_set_time(h, m, s);
          break;
        }
      }
      else {
        *hms[hms_current] += enc_pos;
        if (hms_current == 0 && *hms[hms_current] > 23) {
          *hms[hms_current] = 0;
        }
        else if (hms_current == 0 && *hms[hms_current] < 0) {
          *hms[hms_current] = 23;
        }
        else if (hms_current == 1 && *hms[hms_current] > 59) {
          *hms[hms_current] = 0;
        }
        else if (hms_current == 1 && *hms[hms_current] < 0) {
          *hms[hms_current] = 59;
        }
        else if (hms_current == 2 && *hms[hms_current] > 59) {
          *hms[hms_current] = 0;
        }
        else if (hms_current == 2 && *hms[hms_current] < 0) {
          *hms[hms_current] = 59;
        }
      }
      flash = false;
    }
    else {
      flash = !flash;
    }
  }
}

void set_date() {
  int m = month, d = date, y = year;
  
  char enc_moved = 0;
  boolean enc_pressed = 0;

  do {
    m += enc_moved;
    if (m < 1) {
      m = 12;
    }
    else if (m > 12) {
      m = 1;
    }
    if (enc_pressed) {
      ds3231_set_date(y, m, d);
      break;
    }
    sprintf(display_buf, "Mo %s", month_abbrevs[m - 1]);
    vfd_set_string(display_buf, 0);
  } while (wait_for_input(MENU_TIMEOUT, &enc_moved, &enc_pressed));
  
  enc_moved = 0;
  enc_pressed = 0;
  do {
    d += enc_moved;
    if (d < 1) {
      d = 31;
    }
    else if (d > 31) {
      d = 1;
    }
    if (enc_pressed) {
      ds3231_set_date(y, m, d);
      break;
    }
    sprintf(display_buf, "Day %d", d);
    vfd_set_string(display_buf, 0);
  } while (wait_for_input(MENU_TIMEOUT, &enc_moved, &enc_pressed));
  
  enc_moved = 0;
  enc_pressed = 0;
  do {
    y += enc_moved;
    if (y < 0) {
      y = 99;
    }
    else if (y > 99) {
      y = 0;
    }
    if (enc_pressed) {
      ds3231_set_date(y, m, d);
      break;
    }
    sprintf(display_buf, "Yr 20%02d", y);
    vfd_set_string(display_buf, 0);
  } while (wait_for_input(MENU_TIMEOUT, &enc_moved, &enc_pressed));
}

void set_display_mode() {
  char *modes[] = {
    "hh mm ss",
    "hhmm  DD",
    "hhmm TTF",
    "MMM DD",
    "tttttttt",
    "hhmm  vv",
  };
  
  char enc_moved = 0;
  boolean enc_pressed = 0;
  
  char orig_display_mode = display_mode;

  do {
    display_mode += enc_moved;
    if (display_mode < 0) {
      display_mode = 5;
    }
    else if (display_mode > 5) {
      display_mode = 0;
    }
    if (enc_pressed) {
      save_config();
      orig_display_mode = display_mode;
      break;
    }
    vfd_set_string(modes[display_mode], 0);
  } while (wait_for_input(MENU_TIMEOUT, &enc_moved, &enc_pressed));
  
  display_mode = orig_display_mode;
}

void set_brightness() {
  char enc_moved = 0;
  boolean enc_pressed = 0;

  char orig_brightness = brightness;

  do {
    brightness += enc_moved;
    if (brightness < 0) {
      brightness = 0;
    }
    else if (brightness > 7) {
      brightness = 7;
    }
    
    vfd_data[0] = 0;
    for (int i = 1; i < 9; i++) {
      if (i == 1) {
        vfd_data[i] = VFD_SEG_F | VFD_SEG_E;
      }
      else if (i == 8) {
        vfd_data[i] = VFD_SEG_B | VFD_SEG_C;
      }
      else {
        vfd_data[i] = 0;
      }
      vfd_data[i] |= (brightness == i - 1 ? VFD_SEG_G : 0);
    }
    
    voltage_target = 20.0 + ((brightness + 1) * 3.75);
    
    if (enc_pressed) {
      save_config();
      orig_brightness = brightness;
      break;
    }
    
  } while (wait_for_input(MENU_TIMEOUT, &enc_moved, &enc_pressed));
  
  brightness = orig_brightness;
  voltage_target = 20.0 + ((brightness + 1) * 3.75);
}

void set_bank_mode() {
  char *modes[] = {
    "Off",
    "On",
  };
  
  char enc_moved = 0;
  boolean enc_pressed = 0;
  
  char orig_bank_mode = bank_mode;

  do {
    bank_mode += enc_moved;
    if (bank_mode < 0) {
      bank_mode = 1;
    }
    else if (bank_mode > 1) {
      bank_mode = 0;
    }
    if (enc_pressed) {
      save_config();
      orig_bank_mode = bank_mode;
      break;
    }
    sprintf(display_buf, "Bank %s", modes[bank_mode]);
    vfd_set_string(display_buf, 0);
  } while (wait_for_input(MENU_TIMEOUT, &enc_moved, &enc_pressed));
  
  bank_mode = orig_bank_mode;
}

void main_menu() {
  /*
    TODO
    Change Display to Dsp Mode, add Time Fmt, add Date Fmt, make Bank a Dsp Mode option 
    along with Time, Date. Maybe. Kinda nice to have date/time formats too.
    Also add transition: Scroll, Switch
  */
  char *items[] = {
    "Set Time",
    "Set Date",
    "Display",
    "Britenes",
    "Bank",
    "Exit",
  };
  int items_length = 6;
  
  int index = 0;
  char enc_moved = 0;
  boolean enc_pressed = 0;

  do {
    index += enc_moved;
    if (index < 0) {
      index = items_length - 1;
    }
    else if (index > items_length - 1) {
      index = 0;
    }
    if (enc_pressed) {
      if (index == 0) {
        set_time();
        break;
      }
      else if (index == 1) {
        set_date();
        break;
      }
      else if (index == 2) {
        set_display_mode();
        break;
      }
      else if (index == 3) {
        set_brightness();
        break;
      }
      else if (index == 4) {
        set_bank_mode();
        break;
      }
      else {
        break;
      }
    }
    vfd_set_string(items[index], 0);
  } while (wait_for_input(MENU_TIMEOUT, &enc_moved, &enc_pressed));
}

float c_to_f(float c) {
  return (((9.0 / 5.0) * c) + 32.0);
}

/*
  The main loop of the program is responsible for displaying the current time, checking for input
  from the encoder or button and running the menu system for the user to interact with the clock.
*/
void loop() {
  char enc_moved = 0;
  boolean enc_pressed = 0;
  for (;;) {
    // This effectively defines the refresh rate for the clock data. We wait for input
    // for 10 ms and then refresh the clock.
    if (wait_for_input(10, &enc_moved, &enc_pressed)) {
      main_menu();
    }
    switch (display_mode) {
      case 0: {
        sprintf(display_buf, "%02d:%02d:%02d", hour, minute, second);
        vfd_data[0] = 0;
        break;
      }
      case 1: {
        sprintf(display_buf, "%02d%02d  %02d", hour, minute, date);
        vfd_data[0] = (second % 2 ? VFD_SEG_H : 0);
        break;
      }
      case 2: {
        sprintf(display_buf, "%02d%02d %dF", hour, minute, (int) c_to_f(temperature));
        vfd_data[0] = (second % 2 ? VFD_SEG_H : 0);
        break;
      }
      case 3: {
        sprintf(display_buf, "%s %02d", month_abbrevs[month - 1], date);
        vfd_data[0] = 0;
        break;
      }
      case 4: {
        uint64_t t = (24L * 60L * 60L * 1000L) - ((hour * 60L * 60L * 1000L) + (minute * 60L * 1000L) + (second * 1000L) + millisecond);
        sprintf(display_buf, "%08lu", t);
        vfd_data[0] = 0;
        break;
      }
      case 5: {
        sprintf(display_buf, "%02d%02d  %02d", hour, minute, (int) voltage);
        vfd_data[0] = (second % 2 ? VFD_SEG_H : 0);
        break;
      }
    }
    if (bank_mode) {
      if (second % 12 < 4) {
          sprintf(display_buf, "%02d-%02d-%02d", month, date, year);
          vfd_data[0] = 0;
      }
      else if (second % 12 < 8) {
          sprintf(display_buf, "%dF %dC", (int) c_to_f(temperature), (int) temperature);
          vfd_data[0] = 0;
      }
    }
    vfd_set_string(display_buf, 0);
  }
}


 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

А где сообщение об ошибках?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

И где сообщение об ошибке?

Если вот это: "Wire.send() переименовано в Wire.write()", то что Вам в этой фразе непонятно? Вы и впрямь не знаете, как это исправить?

rezak.69
Offline
Зарегистрирован: 23.03.2019

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ну, так и есть. Вам же написали что имя, которое написано у Вас, изменено на другое и даже написали на какое именно. Вы и впрямь не знаете как это исправлять надо?

P.S. И кстати, впредь ошибки копипастите, пожалейте наши глаза.

rezak.69
Offline
Зарегистрирован: 23.03.2019

Увы , не знаю как исправить подскажите пожалуйста : ЕвгенийП.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Вы меня троллите?

Ну, Вам же написали: "Wire.send() переименовано в Wire.write()"

Ну так и переименуйте у себя в программе все вхождения "Wire.send()" на "Wire.write()".

Когда сделаете, Вам скажут тоже самое про Wire.receive() - и её переименуете.

Чего тут умного-то?

rezak.69
Offline
Зарегистрирован: 23.03.2019

Я Радиотехник увы - не программист....

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Я конечна дико извиняюсь...

Вы предлагаете пожалеть стоматолога который взялся удалить гланды ? Его же никто не заставлял, он сам решил, что сможет.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

И что, радиотехники не понимают слова "переименовано"?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Давайка, обращайся к автору скетча, с этой портянкой, а не сюда