/* Four Channel Thermometer v3 David Johnson-Davies - www.technoblogy.com - 5th December 2020 ATtiny85 @ 8 MHz (internal oscillator; BOD disabled) CC BY 4.0 Licensed under a Creative Commons Attribution 4.0 International license: http://creativecommons.org/licenses/by/4.0/ */ #include // Pins const int clk = 0; const int data = 1; const int dc = 2; const int cs = 3; // One Wire Protocol ********************************************** // Buffer to read data or ROM code uint8_t DataBytes[9]; const int OneWirePin = 4; const int ReadROM = 0x33; const int MatchROM = 0x55; const int SkipROM = 0xCC; const int ConvertT = 0x44; const int ReadScratchpad = 0xBE; inline void PinLow () { DDRB = DDRB | 1<>OneWirePin & 1; } void DelayMicros (int micro) { TCNT1 = 0; TIFR = 1<>1) - 1; while ((TIFR & 1<> 1; } } uint8_t OneWireRead () { uint8_t data = 0; for (int i = 0; i<8; i++) { LowRelease(6, 9); data = data | PinRead()<>1 ^ ((crc & 1) ? 0x8c : 0); } return crc; } // EEPROM handling ********************************************** // Write 8 bytes from buffer to EEPROM void EepromSave (int slot) { for (int i=0; i<8; i++) EEPROM.update(slot*8+i, DataBytes[i]); } // Read 8 bytes from EEPROM to buffer - return CRC int EepromLoad (int slot) { for (int i=0; i<8; i++) DataBytes[i] = EEPROM.read(slot*8+i); return OneWireCRC(8); } // Compare 8 bytes from EEPROM with buffer - return true/false boolean EepromCompare (int slot) { boolean equal = true; for (int i=0; i<8; i++) equal = equal && (DataBytes[i] == EEPROM.read(slot*8+i)); return equal; } // Clear the EEPROM slots void EepromClear () { for (int i=0; i<8; i++) DataBytes[i] = 0xff; for (int i=0; i<4; i++) EepromSave(i); } // OLED 128 x 32 monochrome display ********************************************** // Initialisation sequence for OLED module int const InitLen = 24; const unsigned char Init[InitLen] PROGMEM = { 0xAE, // Display off 0xD5, // Set display clock 0x80, // Recommended value 0xA8, // Set multiplex 0x1F, 0xD3, // Set display offset 0x00, 0x40, // Zero start line 0x8D, // Charge pump 0x14, 0x20, // Memory mode 0x01, // Vertical addressing 0xA1, // 0xA0/0xA1 flip horizontally 0xC8, // 0xC0/0xC8 flip vertically 0xDA, // Set comp ins 0x02, 0x81, // Set contrast 0x7F, // 0x00 to 0xFF 0xD9, // Set pre charge 0xF1, 0xDB, // Set vcom detect 0x40, 0xA6, // Normal (0xA7=Inverse) 0xAF // Display on }; // Write a data byte to the display void Data(uint8_t d) { uint8_t changes = d ^ (d>>1); PORTB = PORTB & ~(1<>= 1) { PINB = 1<=0; i--) { for (int j=1; j<3; j++) { if (((col0>>i & 0b11) == (3-j)) && ((col1>>i & 0b11) == j)) { col0R = col0R | 1<<((i*2)+j); col1L = col1L | 1<<((i*2)+3-j); } } } } Data(col0L); Data(col0L>>8); Data(col0R); Data(col0R>>8); col0L = col1L; col0R = col1R; } col0 = col1; } if (Scale == 1) Data(col0); else { Data(col0L); Data(col0L>>8); Data(col0R); Data(col0R>>8); } PINB = 1<0; d=d/10) { char c = DigitChar(temp, d); if (c == '0' && !dig) c = ' '; else dig = true; PlotChar(c, line, column); column = column + Scale; } PlotChar('`', line, column); column = column + Scale; PlotChar('C', line, column); } // Setup ********************************************** void setup() { // EepromClear(); pinMode(dc, OUTPUT); digitalWrite(dc,HIGH); pinMode(clk, OUTPUT); digitalWrite(clk,HIGH); pinMode(data, OUTPUT); pinMode(cs, OUTPUT); digitalWrite(cs,HIGH); InitDisplay(); ClearDisplay(); OneWireSetup(); Scale = 2; // Check if there's something on the bus cli(); if (OneWireReset() != 0) { PlotChar('?',1,10); for(;;); } int slot; // Find the first free EEPROM slot for (slot=0; slot<4; slot++) { if (EepromLoad(slot) != 0) break; } if (slot < 4) { // Try reading the ROM OneWireWrite(ReadROM); OneWireReadBytes(8); sei(); if (OneWireCRC(8) == 0) { // Check we haven't already got it int j; for (j=0; j>4, line, col); } else PlotChar('X', line, col); } } }