Загрузка данных


echo '#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>

const uint8_t font5x7[] = {
  0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x5F,0x00,0x00, 0x00,0x07,0x00,0x07,0x00, 0x14,0x7F,0x14,0x7F,0x14,
  0x24,0x2A,0x7F,0x2A,0x12, 0x23,0x13,0x08,0x64,0x62, 0x36,0x49,0x55,0x22,0x50, 0x00,0x05,0x03,0x00,0x00,
  0x00,0x1C,0x22,0x41,0x00, 0x00,0x41,0x22,0x1C,0x00, 0x14,0x08,0x3E,0x08,0x14, 0x08,0x08,0x3E,0x08,0x08,
  0x00,0x50,0x30,0x00,0x00, 0x08,0x08,0x08,0x08,0x08, 0x00,0x60,0x60,0x00,0x00, 0x20,0x10,0x08,0x04,0x02,
  0x3E,0x51,0x49,0x45,0x3E, 0x00,0x42,0x7F,0x40,0x00, 0x42,0x61,0x51,0x49,0x46, 0x21,0x41,0x45,0x4B,0x31,
  0x18,0x14,0x12,0x7F,0x10, 0x27,0x45,0x45,0x45,0x39, 0x3C,0x4A,0x49,0x49,0x30, 0x01,0x71,0x09,0x05,0x03,
  0x36,0x49,0x49,0x49,0x36, 0x06,0x49,0x49,0x29,0x1E, 0x00,0x36,0x36,0x00,0x00, 0x00,0x56,0x36,0x00,0x00,
  0x08,0x14,0x22,0x41,0x00, 0x14,0x14,0x14,0x14,0x14, 0x00,0x41,0x22,0x14,0x08, 0x02,0x01,0x51,0x09,0x06,
  0x32,0x49,0x79,0x41,0x3E, 0x7E,0x11,0x11,0x11,0x7E, 0x7F,0x49,0x49,0x49,0x36, 0x3E,0x41,0x41,0x41,0x22,
  0x7F,0x41,0x41,0x22,0x1C, 0x7F,0x49,0x49,0x49,0x41, 0x7F,0x09,0x09,0x09,0x01, 0x3E,0x41,0x49,0x49,0x7A,
  0x7F,0x08,0x08,0x08,0x7F, 0x00,0x41,0x7F,0x41,0x00, 0x20,0x40,0x41,0x3F,0x01, 0x7F,0x08,0x14,0x22,0x41,
  0x7F,0x40,0x40,0x40,0x40, 0x7F,0x02,0x0C,0x02,0x7F, 0x7F,0x04,0x08,0x10,0x7F, 0x3E,0x41,0x41,0x41,0x3E,
  0x7F,0x09,0x09,0x09,0x06, 0x3E,0x41,0x51,0x21,0x5E, 0x7F,0x09,0x19,0x29,0x46, 0x46,0x49,0x49,0x49,0x31,
  0x01,0x01,0x7F,0x01,0x01, 0x3F,0x40,0x40,0x40,0x3F, 0x1F,0x20,0x40,0x20,0x1F, 0x3F,0x40,0x38,0x40,0x3F,
  0x63,0x14,0x08,0x14,0x63, 0x07,0x08,0x70,0x08,0x07, 0x61,0x51,0x49,0x45,0x43
};

const uint8_t font_cyr[][5] = {
  {0x7E,0x11,0x11,0x11,0x7E},
  {0x7F,0x49,0x49,0x49,0x31},
  {0x7F,0x49,0x49,0x49,0x36},
  {0x7F,0x01,0x01,0x01,0x03},
  {0x60,0x3F,0x21,0x3F,0x60},
  {0x7F,0x49,0x49,0x49,0x41},
  {0x77,0x08,0x7F,0x08,0x77},
  {0x41,0x49,0x49,0x49,0x36},
  {0x7F,0x10,0x08,0x04,0x7F},
  {0x7F,0x10,0x09,0x04,0x7F},
  {0x7F,0x08,0x14,0x22,0x41},
  {0x40,0x3E,0x01,0x01,0x7F},
  {0x7F,0x02,0x0C,0x02,0x7F},
  {0x7F,0x08,0x08,0x08,0x7F},
  {0x3E,0x41,0x41,0x41,0x3E},
  {0x7F,0x01,0x01,0x01,0x7F},
  {0x7F,0x09,0x09,0x09,0x06},
  {0x3E,0x41,0x41,0x41,0x22},
  {0x01,0x01,0x7F,0x01,0x01},
  {0x07,0x08,0x70,0x08,0x07},
  {0x0E,0x51,0x7F,0x51,0x0E},
  {0x63,0x14,0x08,0x14,0x63},
  {0x3F,0x20,0x20,0x3F,0x60},
  {0x07,0x08,0x08,0x7F,0x00},
  {0x7F,0x40,0x7F,0x40,0x7F},
  {0x7F,0x40,0x7F,0x40,0x7F},
  {0x01,0x7F,0x48,0x48,0x30},
  {0x7F,0x48,0x48,0x48,0x30},
  {0x7F,0x48,0x30,0x00,0x7F},
  {0x41,0x41,0x49,0x49,0x3E},
  {0x7F,0x08,0x3E,0x41,0x3E},
  {0x46,0x29,0x19,0x09,0x7F}
};

void i2c_init(void) { TWSR = 0; TWBR = 72; }
void i2c_start(uint8_t a) {
  TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
  while (!(TWCR & (1<<TWINT)));
  TWDR = a;
  TWCR = (1<<TWINT)|(1<<TWEN);
  while (!(TWCR & (1<<TWINT)));
}
void i2c_stop(void) { TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN); _delay_us(10); }
void i2c_write(uint8_t d) {
  TWDR = d;
  TWCR = (1<<TWINT)|(1<<TWEN);
  while (!(TWCR & (1<<TWINT)));
}
uint8_t i2c_read_ack(void) {
  TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
  while (!(TWCR & (1<<TWINT)));
  return TWDR;
}
uint8_t i2c_read_nack(void) {
  TWCR = (1<<TWINT)|(1<<TWEN);
  while (!(TWCR & (1<<TWINT)));
  return TWDR;
}

void oled_cmd(uint8_t c) {
  i2c_start(0x3C << 1); i2c_write(0x00); i2c_write(c); i2c_stop();
}
void oled_init(void) {
  oled_cmd(0xAE); oled_cmd(0x20); oled_cmd(0x00); oled_cmd(0xB0);
  oled_cmd(0xC8); oled_cmd(0x00); oled_cmd(0x10); oled_cmd(0x40);
  oled_cmd(0x81); oled_cmd(0x7F); oled_cmd(0xA1); oled_cmd(0xA6);
  oled_cmd(0xA8); oled_cmd(0x3F); oled_cmd(0xA4); oled_cmd(0xD3);
  oled_cmd(0x00); oled_cmd(0xD5); oled_cmd(0x80); oled_cmd(0xD9);
  oled_cmd(0xF1); oled_cmd(0xDA); oled_cmd(0x12); oled_cmd(0xDB);
  oled_cmd(0x40); oled_cmd(0x8D); oled_cmd(0x14); oled_cmd(0xAF);
}
void oled_set_pos(uint8_t col, uint8_t page) {
  oled_cmd(0xB0 | page);
  oled_cmd(0x00 | (col & 0x0F));
  oled_cmd(0x10 | (col >> 4));
}
void oled_clear(void) {
  for (uint8_t p = 0; p < 8; p++) {
    oled_set_pos(0, p);
    i2c_start(0x3C << 1); i2c_write(0x40);
    for (uint8_t i = 0; i < 128; i++) i2c_write(0x00);
    i2c_stop();
  }
}
void oled_draw_5x7(const uint8_t *b) {
  i2c_start(0x3C << 1); i2c_write(0x40);
  for (uint8_t i = 0; i < 5; i++) i2c_write(b[i]);
  i2c_write(0x00);
  i2c_stop();
}
void oled_print(uint8_t col, uint8_t page, const char* s) {
  oled_set_pos(col, page);
  while (*s) {
    uint8_t c = (uint8_t)*s++;
    if (c == 0xD0 || c == 0xD1) {
      uint8_t c2 = (uint8_t)*s++;
      uint8_t idx = 0;
      if (c == 0xD0 && c2 >= 0x90 && c2 <= 0xAF) idx = c2 - 0x90;
      else if (c == 0xD0 && c2 >= 0xB0 && c2 <= 0xBF) idx = c2 - 0xB0;
      else if (c == 0xD1 && c2 >= 0x80 && c2 <= 0x8F) idx = c2 - 0x80 + 16;
      oled_draw_5x7(font_cyr[idx]);
    } else {
      if (c < 32 || c > 90) c = 32;
      oled_draw_5x7(&font5x7[(c - 32) * 5]);
    }
  }
}
void oled_num(uint8_t col, uint8_t page, int32_t n) {
  char buf[10]; int8_t i = 0;
  if (n < 0) { n = -n; oled_print(col, page, "-"); col += 6; }
  if (n == 0) { buf[i++] = 0x30; }
  else { while (n > 0) { buf[i++] = (n % 10) + 0x30; n /= 10; } }
  oled_set_pos(col, page);
  while (--i >= 0) {
    uint8_t c = buf[i];
    oled_draw_5x7(&font5x7[(c - 32) * 5]);
  }
}

uint16_t dig_T1, dig_P1;
int16_t dig_T2, dig_T3, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9;
int32_t t_fine;

void bmp_init(void) {
  i2c_start(0x77 << 1); i2c_write(0x88); i2c_stop();
  i2c_start((0x77 << 1) | 1);
  dig_T1 = i2c_read_ack() | (i2c_read_ack() << 8);
  dig_T2 = i2c_read_ack() | (i2c_read_ack() << 8);
  dig_T3 = i2c_read_ack() | (i2c_read_ack() << 8);
  dig_P1 = i2c_read_ack() | (i2c_read_ack() << 8);
  dig_P2 = i2c_read_ack() | (i2c_read_ack() << 8);
  dig_P3 = i2c_read_ack() | (i2c_read_ack() << 8);
  dig_P4 = i2c_read_ack() | (i2c_read_ack() << 8);
  dig_P5 = i2c_read_ack() | (i2c_read_ack() << 8);
  dig_P6 = i2c_read_ack() | (i2c_read_ack() << 8);
  dig_P7 = i2c_read_ack() | (i2c_read_ack() << 8);
  dig_P8 = i2c_read_ack() | (i2c_read_ack() << 8);
  dig_P9 = i2c_read_ack() | (i2c_read_nack() << 8);
  i2c_stop();
  i2c_start(0x77 << 1); i2c_write(0xF4); i2c_write(0x27); i2c_stop();
}

int32_t bmp_press_mmhg(void) {
  i2c_start(0x77 << 1); i2c_write(0xF7); i2c_stop();
  i2c_start((0x77 << 1) | 1);
  int32_t p_raw = ((int32_t)i2c_read_ack() << 12) | ((int32_t)i2c_read_ack() << 4) | (i2c_read_ack() >> 4);
  int32_t t_raw = ((int32_t)i2c_read_ack() << 12) | ((int32_t)i2c_read_ack() << 4) | (i2c_read_nack() >> 4);
  i2c_stop();

  int32_t v1 = ((((t_raw >> 3) - ((int32_t)dig_T1 << 1))) * ((int32_t)dig_T2)) >> 11;
  int32_t v2 = (((((t_raw >> 4) - ((int32_t)dig_T1)) * ((t_raw >> 4) - ((int32_t)dig_T1))) >> 12) * ((int32_t)dig_T3)) >> 14;
  t_fine = v1 + v2;

  int64_pv1;
  int64_t pv1 = ((int64_t)t_fine) - 128000;
  int64_t pv2 = pv1 * pv1 * (int64_t)dig_P6;
  pv2 = pv2 + ((pv1 * (int64_t)dig_P5) << 17);
  pv2 = pv2 + (((int64_t)dig_P4) << 35);
  pv1 = ((pv1 * pv1 * (int64_t)dig_P3) >> 8) + ((pv1 * (int64_t)dig_P2) << 12);
  pv1 = (((((int64_t)1) << 47) + pv1)) * ((int64_t)dig_P1) >> 33;
  if (pv1 == 0) return 0;
  int64_t p = 1048576 - p_raw;
  p = (((p << 31) - pv2) * 3125) / pv1;
  pv1 = (((int64_t)dig_P9) * (p >> 13) * (p >> 13)) >> 25;
  pv2 = (((int64_t)dig_P8) * p) >> 19;
  p = ((p + pv1 + pv2) >> 8) + (((int64_t)dig_P7) << 4);
  return (int32_t)((p / 256) * 75 / 10000);
}

void aht_init(void) {
  _delay_ms(40);
  i2c_start(0x38 << 1); i2c_write(0xBE); i2c_write(0x08); i2c_write(0x00); i2c_stop();
  _delay_ms(10);
}

void aht_read(int16_t *temp, uint8_t *hum) {
  i2c_start(0x38 << 1); i2c_write(0xAC); i2c_write(0x33); i2c_write(0x00); i2c_stop();
  _delay_ms(80);

  i2c_start((0x38 << 1) | 1);
  uint8_t st = i2c_read_ack();
  if (st & 0x80) {
    _delay_ms(20);
  }
  uint32_t h_raw = ((uint32_t)i2c_read_ack() << 12) | ((uint32_t)i2c_read_ack() << 4);
  uint8_t mid = i2c_read_ack();
  h_raw |= (mid >> 4);
  uint32_t t_raw = ((uint32_t)(mid & 0x0F) << 16) | ((uint32_t)i2c_read_ack() << 8) | i2c_read_nack();
  i2c_stop();

  *hum = (uint8_t)(((uint64_t)h_raw * 100) >> 20);
  *temp = (int16_t)((((int64_t)t_raw * 2000) >> 20) - 500);
}

void render_labels(void) {
  oled_print(20, 0, "МЕТЕОСТАНЦИЯ");
  oled_print(0, 2, "ТЕМП: ");
  oled_print(0, 4, "ВЛАЖ: ");
  oled_print(0, 6, "ДАВЛ: ");
}

void update_screen(void) {
  int16_t t = 0; uint8_t h = 0;
  aht_read(&t, &h);
  int32_t p = bmp_press_mmhg();

  oled_num(45, 2, t / 10);
  oled_print(65, 2, ". ");
  oled_num(75, 2, (t < 0 ? -t : t) % 10);
  oled_print(90, 2, "C  ");

  oled_num(45, 4, h);
  oled_print(70, 4, " %   ");

  oled_num(45, 6, p);
  oled_print(75, 6, " ММ.РТ ");
}

ISR(INT0_vect) {
}

int main(void) {
  DDRD &= ~(1 << PD2);
  PORTD |= (1 << PD2);

  EICRA &= ~((1 << ISC01) | (1 << ISC00));
  EIMSK |= (1 << INT0);
  sei();

  i2c_init();
  _delay_ms(100);
  oled_init();
  bmp_init();
  aht_init();

  while (1) {
    oled_init();
    oled_clear();
    render_labels();
    oled_cmd(0xAF);

    for (uint8_t i = 0; i < 5; i++) {
      update_screen();
      _delay_ms(5000);
    }

    oled_cmd(0xAE);
    _delay_ms(200);

    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    sleep_cpu();
    sleep_disable();
    _delay_ms(200);
  }
}' > meteo.c; and avr-gcc -mmcu=atmega328p -Wall -Os meteo.c -o meteo.elf; and avr-objcopy -O ihex -R .eeprom meteo.elf meteo.hex; and avrdude -p m328p -c arduino -P /dev/ttyUSB0 -b 57600 -D -U flash:w:meteo.hex:i