//Tiny HVSP V1.4 //Platine arduino uno (mini pro flashé en uno) //validé pour T13 , T25 , T45 , T84 , T85 , T24 // =================================================================================== // Libraries and Definitions // =================================================================================== // Libraries #include // for GPIO #include // to store data in programm memory #include // for delays // Pin definitions #define RST_PIN PB5 //13 // 12V !RESET Pin 1 of target device #define SCI_PIN PB4 //12 // Serial Clock Input (SCI) Pin 2 of target device #define SDO_PIN PB3 //11 // Serial Data Output (SDO) Pin 7 of target device #define SII_PIN PB2 //10 // Serial Instruction Input (SII) Pin 6 of target device #define SDI_PIN PB1 //9 // Serial Data Input (SDI) Pin 5 of target device #define VCC_PIN PB0 //8 // Target VCC Pin 8 of target device #define I2C_SCL PC5 // I2C Serial Clock (SCK) #define I2C_SDA PC4 // I2C Serial Data (SDA) #define BUTTON PD7 // OK-Button #define ERRORLED PD4 //4 led rouge #define GOODLED PD3 //3 led verte // Global variables uint8_t inLFUSE, inHFUSE, inEFUSE; // for reading fuses uint8_t outLFUSE, outHFUSE, outEFUSE; // for writing fuses uint8_t inLOCK; // for reading lock bits uint16_t signature; // for reading signature // =================================================================================== // I2C Implementation // =================================================================================== // I2C macros #define I2C_SDA_HIGH() DDRC &= ~(1< pulled HIGH by resistor #define I2C_SDA_LOW() DDRC |= (1< pulled LOW by MCU #define I2C_SCL_HIGH() DDRC &= ~(1< pulled HIGH by resistor #define I2C_SCL_LOW() DDRC |= (1< pulled LOW by MCU #define I2C_DELAY() asm("lpm") // delay 3 clock cycles #define I2C_CLOCKOUT() I2C_SCL_HIGH();I2C_DELAY();I2C_SCL_LOW() // clock out // I2C init function void I2C_init(void) { DDRC &= ~((1< lines released PORTC &= ~((1< slave reads the bit } I2C_DELAY(); // delay 3 clock cycles I2C_SDA_HIGH(); // release SDA for ACK bit of slave I2C_CLOCKOUT(); // 9th clock pulse is for the ignored ACK bit } // I2C start transmission void I2C_start(uint8_t addr) { I2C_SDA_LOW(); // start condition: SDA goes LOW first I2C_SCL_LOW(); // start condition: SCL goes LOW second I2C_write(addr); // send slave address } // I2C stop transmission void I2C_stop(void) { I2C_SDA_LOW(); // prepare SDA for LOW to HIGH transition I2C_SCL_HIGH(); // stop condition: SCL goes HIGH first I2C_SDA_HIGH(); // stop condition: SDA goes HIGH second } // =================================================================================== // OLED Implementation // =================================================================================== // OLED definitions #define OLED_ADDR 0x78 // OLED write address #define OLED_CMD_MODE 0x00 // set command mode #define OLED_DAT_MODE 0x40 // set data mode #define OLED_INIT_LEN 9 // length of init command array // OLED 5x8 pixels character set const uint8_t OLED_FONT[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2F, 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, 0x00, 0xA0, 0x60, 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, 0x59, 0x51, 0x3E, 0x7C, 0x12, 0x11, 0x12, 0x7C, 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, 0x00, 0x7F, 0x41, 0x41, 0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x41, 0x41, 0x7F, 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x01, 0x02, 0x04, 0x00, 0x20, 0x54, 0x54, 0x54, 0x78, 0x7F, 0x48, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x44, 0x20, 0x38, 0x44, 0x44, 0x48, 0x7F, 0x38, 0x54, 0x54, 0x54, 0x18, 0x08, 0x7E, 0x09, 0x01, 0x02, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x44, 0x7D, 0x40, 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, 0x7C, 0x08, 0x04, 0x04, 0x78, 0x38, 0x44, 0x44, 0x44, 0x38, 0xFC, 0x24, 0x24, 0x24, 0x18, 0x18, 0x24, 0x24, 0x18, 0xFC, 0x7C, 0x08, 0x04, 0x04, 0x08, 0x48, 0x54, 0x54, 0x54, 0x20, 0x04, 0x3F, 0x44, 0x40, 0x20, 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x44, 0x28, 0x10, 0x28, 0x44, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x08, 0x36, 0x41, 0x41, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x41, 0x41, 0x36, 0x08, 0x08, 0x04, 0x08, 0x10, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; // OLED init settings const uint8_t OLED_INIT_CMD[] PROGMEM = { 0xC8, 0xA1, // flip screen 0xA8, 0x1F, // set multiplex ratio 0xDA, 0x02, // set com pins hardware configuration 0x8D, 0x14, // set DC-DC enable 0xAF // display on }; // OLED variables uint8_t OLED_x, OLED_y; // current cursor position // OLED init function void OLED_init(void) { I2C_init(); // initialize I2C first I2C_start(OLED_ADDR); // start transmission to OLED I2C_write(OLED_CMD_MODE); // set command mode for(uint8_t i = 0; i < OLED_INIT_LEN; i++) I2C_write(pgm_read_byte(&OLED_INIT_CMD[i])); // send the command bytes I2C_stop(); // stop transmission } // OLED set the cursor void OLED_setCursor(uint8_t xpos, uint8_t ypos) { I2C_start(OLED_ADDR); // start transmission to OLED I2C_write(OLED_CMD_MODE); // set command mode I2C_write(xpos & 0x0F); // set low nibble of start column I2C_write(0x10 | (xpos >> 4)); // set high nibble of start column I2C_write(0xB0 | (ypos & 0x07)); // set start page I2C_stop(); // stop transmission OLED_x = xpos; OLED_y = ypos; // set the cursor variables } // OLED clear line void OLED_clearLine(uint8_t line) { OLED_setCursor(0, line); // set cursor to line start I2C_start(OLED_ADDR); // start transmission to OLED I2C_write(OLED_DAT_MODE); // set data mode for(uint8_t i=128; i; i--) I2C_write(0x00); // clear the line I2C_stop(); // stop transmission } // OLED clear screen void OLED_clearScreen(void) { for(uint8_t i=0; i<4; i++) // 4 lines OLED_clearLine(i); // clear line } // OLED print a single character void OLED_printChar(char c) { uint16_t ptr = c - 32; // character pointer ptr += ptr << 2; // -> ptr = (ch - 32) * 5; I2C_write(0x00); // write space between characters for(uint8_t i=5 ; i; i--) I2C_write(pgm_read_byte(&OLED_FONT[ptr++])); OLED_x += 6; // update cursor if(OLED_x > 122) { // line end ? I2C_stop(); // stop data transmission OLED_setCursor(0,++OLED_y); // set next line start I2C_start(OLED_ADDR); // start transmission to OLED I2C_write(OLED_DAT_MODE); // set data mode } } // OLED print a string from program memory void OLED_printPrg(const char* p) { I2C_start(OLED_ADDR); // start transmission to OLED I2C_write(OLED_DAT_MODE); // set data mode char ch = pgm_read_byte(p); // read first character from program memory while(ch) { // repeat until string terminator OLED_printChar(ch); // print character on OLED ch = pgm_read_byte(++p); // read next character } I2C_stop(); // stop transmission } // OLED convert byte nibble into hex character and prints it void OLED_printNibble(uint8_t nibble) { char c; if(nibble <= 9) c = '0' + nibble; else c = 'A' + nibble - 10; OLED_printChar(c); } // OLED print byte as hex void OLED_printHex(uint8_t value) { I2C_start(OLED_ADDR); // start transmission to OLED I2C_write(OLED_DAT_MODE); // set data mode OLED_printNibble(value >> 4); // print high nibble OLED_printNibble(value & 0x0F); // print low nibble I2C_stop(); // stop transmission } // =================================================================================== // High-Voltage Serial Programmer Implementation // =================================================================================== // Desired fuse configuration (defaults) for ATtiny13 #define T13_LFUSE 0x6A #define T13_HFUSE 0xFF // Desired fuse configuration (defaults) for ATtiny25/45/85 #define Tx5_LFUSE 0x62 #define Tx5_HFUSE 0xDF // Desired fuse configuration (defaults) for ATtiny24/44/84 #define Tx4_LFUSE 0xE2 #define Tx4_HFUSE 0xDF // Signatures #define T13_SIG 0x9007 #define T15_SIG 0x9006 #define T24_SIG 0x910b #define T25_SIG 0x9108 #define T44_SIG 0x9207 #define T45_SIG 0x9206 #define T84_SIG 0x930c #define T85_SIG 0x930b // HVSP macros #define HVSP_RST_12V() PORTB &= ~(1< to retry. "; const char EraseScreen[] PROGMEM = "Error burning fuses !" "Press to perform" "a chip erase and " "retry burning fuses. "; const char DetectedStr[] PROGMEM = "Detected: "; const char ATtinyStr[] PROGMEM = "ATtiny"; const char ErrorStr[] PROGMEM = " Error !"; const char DefaultStr[] PROGMEM = " to burn defaults"; const char BurnedStr[] PROGMEM = "Fuses burned "; const char QuitStr[] PROGMEM = "Press to quit. "; int main(void) { // Setup DDRB |= (1< shut off 12V PORTD |= (1<