ArduinoISP.ino 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858
  1. //AVRISP Specifique pour platine HVSPreset
  2. #define I2C_SCL PC5 // I2C Serial Clock (SCK)
  3. #define I2C_SDA PC4 // I2C Serial Data (SDA)
  4. #define I2C_SDA_HIGH() DDRC &= ~(1<<I2C_SDA) // release SDA -> pulled HIGH by resistor
  5. #define I2C_SDA_LOW() DDRC |= (1<<I2C_SDA) // SDA as output -> pulled LOW by MCU
  6. #define I2C_SCL_HIGH() DDRC &= ~(1<<I2C_SCL) // release SCL -> pulled HIGH by resistor
  7. #define I2C_SCL_LOW() DDRC |= (1<<I2C_SCL) // SCL as output -> pulled LOW by MCU
  8. #define I2C_DELAY() asm("lpm") // delay 3 clock cycles
  9. #define I2C_CLOCKOUT() I2C_SCL_HIGH();I2C_DELAY();I2C_SCL_LOW() // clock out
  10. #include "Arduino.h"
  11. #undef SERIAL
  12. #define PROG_FLICKER true
  13. // Configure SPI clock (in Hz).
  14. // E.g. for an ATtiny @ 128 kHz: the datasheet states that both the high and low
  15. // SPI clock pulse must be > 2 CPU cycles, so take 3 cycles i.e. divide target
  16. // f_cpu by 6:
  17. // #define SPI_CLOCK (128000/6)
  18. //
  19. // A clock slow enough for an ATtiny85 @ 1 MHz, is a reasonable default:
  20. #define SPI_CLOCK (1000000/6)
  21. // Select hardware or software SPI, depending on SPI clock.
  22. // Currently only for AVR, for other architectures (Due, Zero,...), hardware SPI
  23. // is probably too fast anyway.
  24. #if defined(ARDUINO_ARCH_AVR)
  25. #if SPI_CLOCK > (F_CPU / 128)
  26. #define USE_HARDWARE_SPI
  27. #endif
  28. #endif
  29. // Configure which pins to use:
  30. #define VCC 8
  31. #define RESET 13 // Use pin 10 to reset the target rather than SS
  32. #define PIN_MOSI 9
  33. #define PIN_MISO 10
  34. #define PIN_SCK 11
  35. #define PIN2 12
  36. // By default, use hardware SPI pins:
  37. #ifndef PIN_MOSI
  38. #define PIN_MOSI MOSI
  39. #endif
  40. #ifndef PIN_MISO
  41. #define PIN_MISO MISO
  42. #endif
  43. #ifndef PIN_SCK
  44. #define PIN_SCK SCK
  45. #endif
  46. // Force bitbanged SPI if not using the hardware SPI pins:
  47. #if (PIN_MISO != MISO) || (PIN_MOSI != MOSI) || (PIN_SCK != SCK)
  48. #undef USE_HARDWARE_SPI
  49. #endif
  50. // Configure the serial port to use.
  51. //
  52. // Prefer the USB virtual serial port (aka. native USB port), if the Arduino has one:
  53. // - it does not autoreset (except for the magic baud rate of 1200).
  54. // - it is more reliable because of USB handshaking.
  55. //
  56. // Leonardo and similar have an USB virtual serial port: 'Serial'.
  57. // Due and Zero have an USB virtual serial port: 'SerialUSB'.
  58. //
  59. // On the Due and Zero, 'Serial' can be used too, provided you disable autoreset.
  60. // To use 'Serial': #define SERIAL Serial
  61. #ifdef SERIAL_PORT_USBVIRTUAL
  62. #define SERIAL SERIAL_PORT_USBVIRTUAL
  63. #else
  64. #define SERIAL Serial
  65. #endif
  66. // Configure the baud rate:
  67. #define BAUDRATE 19200
  68. // #define BAUDRATE 115200
  69. // #define BAUDRATE 1000000
  70. #define HWVER 2
  71. #define SWMAJ 1
  72. #define SWMIN 18
  73. // STK Definitions
  74. #define STK_OK 0x10
  75. #define STK_FAILED 0x11
  76. #define STK_UNKNOWN 0x12
  77. #define STK_INSYNC 0x14
  78. #define STK_NOSYNC 0x15
  79. #define CRC_EOP 0x20 //ok it is a space...
  80. void pulse(int pin, int times);
  81. #ifdef USE_HARDWARE_SPI
  82. #include "SPI.h"
  83. #else
  84. #define SPI_MODE0 0x00
  85. #if !defined(ARDUINO_API_VERSION) || ARDUINO_API_VERSION != 10001 // A SPISettings class is declared by ArduinoCore-API 1.0.1
  86. class SPISettings {
  87. public:
  88. // clock is in Hz
  89. SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) : clockFreq(clock) {
  90. (void) bitOrder;
  91. (void) dataMode;
  92. };
  93. uint32_t getClockFreq() const {
  94. return clockFreq;
  95. }
  96. private:
  97. uint32_t clockFreq;
  98. };
  99. #endif // !defined(ARDUINO_API_VERSION)
  100. class BitBangedSPI {
  101. public:
  102. void begin() {
  103. digitalWrite(PIN_SCK, LOW);
  104. digitalWrite(PIN_MOSI, LOW);
  105. pinMode(PIN_SCK, OUTPUT);
  106. pinMode(PIN_MOSI, OUTPUT);
  107. pinMode(PIN_MISO, INPUT);
  108. }
  109. void beginTransaction(SPISettings settings) {
  110. pulseWidth = (500000 + settings.getClockFreq() - 1) / settings.getClockFreq();
  111. if (pulseWidth == 0) {
  112. pulseWidth = 1;
  113. }
  114. }
  115. void end() {}
  116. uint8_t transfer(uint8_t b) {
  117. for (unsigned int i = 0; i < 8; ++i) {
  118. digitalWrite(PIN_MOSI, (b & 0x80) ? HIGH : LOW);
  119. digitalWrite(PIN_SCK, HIGH);
  120. delayMicroseconds(pulseWidth);
  121. b = (b << 1) | digitalRead(PIN_MISO);
  122. digitalWrite(PIN_SCK, LOW); // slow pulse
  123. delayMicroseconds(pulseWidth);
  124. }
  125. return b;
  126. }
  127. private:
  128. unsigned long pulseWidth; // in microseconds
  129. };
  130. static BitBangedSPI SPI;
  131. #endif
  132. const char TitleScreen[] PROGMEM =
  133. " AVRISP Mode: "
  134. " "
  135. "Disconnect 12 Volts !";
  136. void setup() {
  137. SERIAL.begin(BAUDRATE);
  138. pinMode(VCC,OUTPUT);
  139. pinMode(PIN2,OUTPUT);
  140. digitalWrite(VCC,HIGH);
  141. digitalWrite(PIN2,LOW);
  142. reset_target(false);
  143. OLED_init();
  144. OLED_clearScreen();
  145. OLED_setCursor(0,0);
  146. OLED_printPrg(TitleScreen);
  147. }
  148. int ISPError = 0;
  149. int pmode = 0;
  150. // address for reading and writing, set by 'U' command
  151. unsigned int here;
  152. uint8_t buff[256]; // global block storage
  153. #define beget16(addr) (*addr * 256 + *(addr+1) )
  154. typedef struct param {
  155. uint8_t devicecode;
  156. uint8_t revision;
  157. uint8_t progtype;
  158. uint8_t parmode;
  159. uint8_t polling;
  160. uint8_t selftimed;
  161. uint8_t lockbytes;
  162. uint8_t fusebytes;
  163. uint8_t flashpoll;
  164. uint16_t eeprompoll;
  165. uint16_t pagesize;
  166. uint16_t eepromsize;
  167. uint32_t flashsize;
  168. }
  169. parameter;
  170. parameter param;
  171. // this provides a heartbeat on pin 9, so you can tell the software is running.
  172. uint8_t hbval = 128;
  173. int8_t hbdelta = 8;
  174. void heartbeat() {
  175. static unsigned long last_time = 0;
  176. unsigned long now = millis();
  177. if ((now - last_time) < 40) {
  178. return;
  179. }
  180. last_time = now;
  181. if (hbval > 192) {
  182. hbdelta = -hbdelta;
  183. }
  184. if (hbval < 32) {
  185. hbdelta = -hbdelta;
  186. }
  187. hbval += hbdelta;
  188. }
  189. static bool rst_active_high;
  190. void reset_target(bool reset) {
  191. digitalWrite(RESET, ((reset && rst_active_high) || (!reset && !rst_active_high)) ? HIGH : LOW);
  192. }
  193. void loop(void) {
  194. // is pmode active?
  195. if (pmode) {
  196. } else {
  197. }
  198. // is there an error?
  199. if (ISPError) {
  200. } else {
  201. }
  202. // light the heartbeat LED
  203. heartbeat();
  204. if (SERIAL.available()) {
  205. avrisp();
  206. }
  207. }
  208. uint8_t getch() {
  209. while (!SERIAL.available());
  210. return SERIAL.read();
  211. }
  212. void fill(int n) {
  213. for (int x = 0; x < n; x++) {
  214. buff[x] = getch();
  215. }
  216. }
  217. #define PTIME 30
  218. void pulse(int pin, int times) {
  219. do {
  220. digitalWrite(pin, HIGH);
  221. delay(PTIME);
  222. digitalWrite(pin, LOW);
  223. delay(PTIME);
  224. } while (times--);
  225. }
  226. void prog_lamp(int state) {
  227. if (PROG_FLICKER) {
  228. }
  229. }
  230. uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
  231. SPI.transfer(a);
  232. SPI.transfer(b);
  233. SPI.transfer(c);
  234. return SPI.transfer(d);
  235. }
  236. void empty_reply() {
  237. if (CRC_EOP == getch()) {
  238. SERIAL.print((char)STK_INSYNC);
  239. SERIAL.print((char)STK_OK);
  240. } else {
  241. ISPError++;
  242. SERIAL.print((char)STK_NOSYNC);
  243. }
  244. }
  245. void breply(uint8_t b) {
  246. if (CRC_EOP == getch()) {
  247. SERIAL.print((char)STK_INSYNC);
  248. SERIAL.print((char)b);
  249. SERIAL.print((char)STK_OK);
  250. } else {
  251. ISPError++;
  252. SERIAL.print((char)STK_NOSYNC);
  253. }
  254. }
  255. void get_version(uint8_t c) {
  256. switch (c) {
  257. case 0x80:
  258. breply(HWVER);
  259. break;
  260. case 0x81:
  261. breply(SWMAJ);
  262. break;
  263. case 0x82:
  264. breply(SWMIN);
  265. break;
  266. case 0x93:
  267. breply('S'); // serial programmer
  268. break;
  269. default:
  270. breply(0);
  271. }
  272. }
  273. void set_parameters() {
  274. // call this after reading parameter packet into buff[]
  275. param.devicecode = buff[0];
  276. param.revision = buff[1];
  277. param.progtype = buff[2];
  278. param.parmode = buff[3];
  279. param.polling = buff[4];
  280. param.selftimed = buff[5];
  281. param.lockbytes = buff[6];
  282. param.fusebytes = buff[7];
  283. param.flashpoll = buff[8];
  284. // ignore buff[9] (= buff[8])
  285. // following are 16 bits (big endian)
  286. param.eeprompoll = beget16(&buff[10]);
  287. param.pagesize = beget16(&buff[12]);
  288. param.eepromsize = beget16(&buff[14]);
  289. // 32 bits flashsize (big endian)
  290. param.flashsize = buff[16] * 0x01000000
  291. + buff[17] * 0x00010000
  292. + buff[18] * 0x00000100
  293. + buff[19];
  294. // AVR devices have active low reset, AT89Sx are active high
  295. rst_active_high = (param.devicecode >= 0xe0);
  296. }
  297. void start_pmode() {
  298. // Reset target before driving PIN_SCK or PIN_MOSI
  299. // SPI.begin() will configure SS as output, so SPI master mode is selected.
  300. // We have defined RESET as pin 10, which for many Arduinos is not the SS pin.
  301. // So we have to configure RESET as output here,
  302. // (reset_target() first sets the correct level)
  303. reset_target(false); //true
  304. pinMode(RESET, OUTPUT);
  305. SPI.begin();
  306. SPI.beginTransaction(SPISettings(SPI_CLOCK, MSBFIRST, SPI_MODE0));
  307. // See AVR datasheets, chapter "SERIAL_PRG Programming Algorithm":
  308. // Pulse RESET after PIN_SCK is low:
  309. digitalWrite(PIN_SCK, LOW);
  310. delay(20); // discharge PIN_SCK, value arbitrarily chosen
  311. reset_target(true); //false
  312. // Pulse must be minimum 2 target CPU clock cycles so 100 usec is ok for CPU
  313. // speeds above 20 KHz
  314. delayMicroseconds(100);
  315. reset_target(false); //true
  316. // Send the enable programming command:
  317. delay(50); // datasheet: must be > 20 msec
  318. spi_transaction(0xAC, 0x53, 0x00, 0x00);
  319. pmode = 1;
  320. }
  321. void end_pmode() {
  322. SPI.end();
  323. // We're about to take the target out of reset so configure SPI pins as input
  324. pinMode(PIN_MOSI, INPUT);
  325. pinMode(PIN_SCK, INPUT);
  326. reset_target(true); //false
  327. pinMode(RESET, INPUT);
  328. pmode = 0;
  329. }
  330. void universal() {
  331. uint8_t ch;
  332. fill(4);
  333. ch = spi_transaction(buff[0], buff[1], buff[2], buff[3]);
  334. breply(ch);
  335. }
  336. void flash(uint8_t hilo, unsigned int addr, uint8_t data) {
  337. spi_transaction(0x40 + 8 * hilo,
  338. addr >> 8 & 0xFF,
  339. addr & 0xFF,
  340. data);
  341. }
  342. void commit(unsigned int addr) {
  343. if (PROG_FLICKER) {
  344. prog_lamp(LOW);
  345. }
  346. spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0);
  347. if (PROG_FLICKER) {
  348. delay(PTIME);
  349. prog_lamp(HIGH);
  350. }
  351. }
  352. unsigned int current_page() {
  353. if (param.pagesize == 32) {
  354. return here & 0xFFFFFFF0;
  355. }
  356. if (param.pagesize == 64) {
  357. return here & 0xFFFFFFE0;
  358. }
  359. if (param.pagesize == 128) {
  360. return here & 0xFFFFFFC0;
  361. }
  362. if (param.pagesize == 256) {
  363. return here & 0xFFFFFF80;
  364. }
  365. return here;
  366. }
  367. void write_flash(int length) {
  368. fill(length);
  369. if (CRC_EOP == getch()) {
  370. SERIAL.print((char) STK_INSYNC);
  371. SERIAL.print((char) write_flash_pages(length));
  372. } else {
  373. ISPError++;
  374. SERIAL.print((char) STK_NOSYNC);
  375. }
  376. }
  377. uint8_t write_flash_pages(int length) {
  378. int x = 0;
  379. unsigned int page = current_page();
  380. while (x < length) {
  381. if (page != current_page()) {
  382. commit(page);
  383. page = current_page();
  384. }
  385. flash(LOW, here, buff[x++]);
  386. flash(HIGH, here, buff[x++]);
  387. here++;
  388. }
  389. commit(page);
  390. return STK_OK;
  391. }
  392. #define EECHUNK (32)
  393. uint8_t write_eeprom(unsigned int length) {
  394. // here is a word address, get the byte address
  395. unsigned int start = here * 2;
  396. unsigned int remaining = length;
  397. if (length > param.eepromsize) {
  398. ISPError++;
  399. return STK_FAILED;
  400. }
  401. while (remaining > EECHUNK) {
  402. write_eeprom_chunk(start, EECHUNK);
  403. start += EECHUNK;
  404. remaining -= EECHUNK;
  405. }
  406. write_eeprom_chunk(start, remaining);
  407. return STK_OK;
  408. }
  409. // write (length) bytes, (start) is a byte address
  410. uint8_t write_eeprom_chunk(unsigned int start, unsigned int length) {
  411. // this writes byte-by-byte, page writing may be faster (4 bytes at a time)
  412. fill(length);
  413. prog_lamp(LOW);
  414. for (unsigned int x = 0; x < length; x++) {
  415. unsigned int addr = start + x;
  416. spi_transaction(0xC0, (addr >> 8) & 0xFF, addr & 0xFF, buff[x]);
  417. delay(45);
  418. }
  419. prog_lamp(HIGH);
  420. return STK_OK;
  421. }
  422. void program_page() {
  423. char result = (char) STK_FAILED;
  424. unsigned int length = 256 * getch();
  425. length += getch();
  426. char memtype = getch();
  427. // flash memory @here, (length) bytes
  428. if (memtype == 'F') {
  429. write_flash(length);
  430. return;
  431. }
  432. if (memtype == 'E') {
  433. result = (char)write_eeprom(length);
  434. if (CRC_EOP == getch()) {
  435. SERIAL.print((char) STK_INSYNC);
  436. SERIAL.print(result);
  437. } else {
  438. ISPError++;
  439. SERIAL.print((char) STK_NOSYNC);
  440. }
  441. return;
  442. }
  443. SERIAL.print((char)STK_FAILED);
  444. return;
  445. }
  446. uint8_t flash_read(uint8_t hilo, unsigned int addr) {
  447. return spi_transaction(0x20 + hilo * 8,
  448. (addr >> 8) & 0xFF,
  449. addr & 0xFF,
  450. 0);
  451. }
  452. char flash_read_page(int length) {
  453. for (int x = 0; x < length; x += 2) {
  454. uint8_t low = flash_read(LOW, here);
  455. SERIAL.print((char) low);
  456. uint8_t high = flash_read(HIGH, here);
  457. SERIAL.print((char) high);
  458. here++;
  459. }
  460. return STK_OK;
  461. }
  462. char eeprom_read_page(int length) {
  463. // here again we have a word address
  464. int start = here * 2;
  465. for (int x = 0; x < length; x++) {
  466. int addr = start + x;
  467. uint8_t ee = spi_transaction(0xA0, (addr >> 8) & 0xFF, addr & 0xFF, 0xFF);
  468. SERIAL.print((char) ee);
  469. }
  470. return STK_OK;
  471. }
  472. void read_page() {
  473. char result = (char)STK_FAILED;
  474. int length = 256 * getch();
  475. length += getch();
  476. char memtype = getch();
  477. if (CRC_EOP != getch()) {
  478. ISPError++;
  479. SERIAL.print((char) STK_NOSYNC);
  480. return;
  481. }
  482. SERIAL.print((char) STK_INSYNC);
  483. if (memtype == 'F') {
  484. result = flash_read_page(length);
  485. }
  486. if (memtype == 'E') {
  487. result = eeprom_read_page(length);
  488. }
  489. SERIAL.print(result);
  490. }
  491. void read_signature() {
  492. if (CRC_EOP != getch()) {
  493. ISPError++;
  494. SERIAL.print((char) STK_NOSYNC);
  495. return;
  496. }
  497. SERIAL.print((char) STK_INSYNC);
  498. uint8_t high = spi_transaction(0x30, 0x00, 0x00, 0x00);
  499. SERIAL.print((char) high);
  500. uint8_t middle = spi_transaction(0x30, 0x00, 0x01, 0x00);
  501. SERIAL.print((char) middle);
  502. uint8_t low = spi_transaction(0x30, 0x00, 0x02, 0x00);
  503. SERIAL.print((char) low);
  504. SERIAL.print((char) STK_OK);
  505. }
  506. //////////////////////////////////////////
  507. //////////////////////////////////////////
  508. ////////////////////////////////////
  509. ////////////////////////////////////
  510. void avrisp() {
  511. uint8_t ch = getch();
  512. switch (ch) {
  513. case '0': // signon
  514. ISPError = 0;
  515. empty_reply();
  516. break;
  517. case '1':
  518. if (getch() == CRC_EOP) {
  519. SERIAL.print((char) STK_INSYNC);
  520. SERIAL.print("AVR ISP");
  521. SERIAL.print((char) STK_OK);
  522. } else {
  523. ISPError++;
  524. SERIAL.print((char) STK_NOSYNC);
  525. }
  526. break;
  527. case 'A':
  528. get_version(getch());
  529. break;
  530. case 'B':
  531. fill(20);
  532. set_parameters();
  533. empty_reply();
  534. break;
  535. case 'E': // extended parameters - ignore for now
  536. fill(5);
  537. empty_reply();
  538. break;
  539. case 'P':
  540. if (!pmode) {
  541. start_pmode();
  542. }
  543. empty_reply();
  544. break;
  545. case 'U': // set address (word)
  546. here = getch();
  547. here += 256 * getch();
  548. empty_reply();
  549. break;
  550. case 0x60: //STK_PROG_FLASH
  551. getch(); // low addr
  552. getch(); // high addr
  553. empty_reply();
  554. break;
  555. case 0x61: //STK_PROG_DATA
  556. getch(); // data
  557. empty_reply();
  558. break;
  559. case 0x64: //STK_PROG_PAGE
  560. program_page();
  561. break;
  562. case 0x74: //STK_READ_PAGE 't'
  563. read_page();
  564. break;
  565. case 'V': //0x56
  566. universal();
  567. break;
  568. case 'Q': //0x51
  569. ISPError = 0;
  570. end_pmode();
  571. empty_reply();
  572. break;
  573. case 0x75: //STK_READ_SIGN 'u'
  574. read_signature();
  575. break;
  576. // expecting a command, not CRC_EOP
  577. // this is how we can get back in sync
  578. case CRC_EOP:
  579. ISPError++;
  580. SERIAL.print((char) STK_NOSYNC);
  581. break;
  582. // anything else we will return STK_UNKNOWN
  583. default:
  584. ISPError++;
  585. if (CRC_EOP == getch()) {
  586. SERIAL.print((char)STK_UNKNOWN);
  587. } else {
  588. SERIAL.print((char)STK_NOSYNC);
  589. }
  590. }
  591. }
  592. void I2C_init(void) {
  593. DDRC &= ~((1<<I2C_SDA)|(1<<I2C_SCL)); // pins as input (HIGH-Z) -> lines released
  594. PORTC &= ~((1<<I2C_SDA)|(1<<I2C_SCL)); // should be LOW when as ouput
  595. }
  596. void I2C_write(uint8_t data) {
  597. for(uint8_t i = 8; i; i--, data<<=1) { // transmit 8 bits, MSB first
  598. (data & 0x80) ? (I2C_SDA_HIGH()) : (I2C_SDA_LOW()); // SDA HIGH if bit is 1
  599. I2C_CLOCKOUT(); // clock out -> slave reads the bit
  600. }
  601. I2C_DELAY(); // delay 3 clock cycles
  602. I2C_SDA_HIGH(); // release SDA for ACK bit of slave
  603. I2C_CLOCKOUT(); // 9th clock pulse is for the ignored ACK bit
  604. }
  605. // I2C start transmission
  606. void I2C_start(uint8_t addr) {
  607. I2C_SDA_LOW(); // start condition: SDA goes LOW first
  608. I2C_SCL_LOW(); // start condition: SCL goes LOW second
  609. I2C_write(addr); // send slave address
  610. }
  611. // I2C stop transmission
  612. void I2C_stop(void) {
  613. I2C_SDA_LOW(); // prepare SDA for LOW to HIGH transition
  614. I2C_SCL_HIGH(); // stop condition: SCL goes HIGH first
  615. I2C_SDA_HIGH(); // stop condition: SDA goes HIGH second
  616. }
  617. // ===================================================================================
  618. // OLED Implementation
  619. // ===================================================================================
  620. // OLED definitions
  621. #define OLED_ADDR 0x78 // OLED write address
  622. #define OLED_CMD_MODE 0x00 // set command mode
  623. #define OLED_DAT_MODE 0x40 // set data mode
  624. #define OLED_INIT_LEN 9 // length of init command array
  625. // OLED 5x8 pixels character set
  626. const uint8_t OLED_FONT[] PROGMEM = {
  627. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00,
  628. 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x23, 0x13, 0x08, 0x64, 0x62,
  629. 0x36, 0x49, 0x55, 0x22, 0x50, 0x00, 0x05, 0x03, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x41, 0x00,
  630. 0x00, 0x41, 0x22, 0x1C, 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, 0x08, 0x08, 0x3E, 0x08, 0x08,
  631. 0x00, 0x00, 0xA0, 0x60, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x60, 0x60, 0x00, 0x00,
  632. 0x20, 0x10, 0x08, 0x04, 0x02, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x42, 0x7F, 0x40, 0x00,
  633. 0x42, 0x61, 0x51, 0x49, 0x46, 0x21, 0x41, 0x45, 0x4B, 0x31, 0x18, 0x14, 0x12, 0x7F, 0x10,
  634. 0x27, 0x45, 0x45, 0x45, 0x39, 0x3C, 0x4A, 0x49, 0x49, 0x30, 0x01, 0x71, 0x09, 0x05, 0x03,
  635. 0x36, 0x49, 0x49, 0x49, 0x36, 0x06, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x36, 0x36, 0x00, 0x00,
  636. 0x00, 0x56, 0x36, 0x00, 0x00, 0x08, 0x14, 0x22, 0x41, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14,
  637. 0x00, 0x41, 0x22, 0x14, 0x08, 0x02, 0x01, 0x51, 0x09, 0x06, 0x32, 0x49, 0x59, 0x51, 0x3E,
  638. 0x7C, 0x12, 0x11, 0x12, 0x7C, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x3E, 0x41, 0x41, 0x41, 0x22,
  639. 0x7F, 0x41, 0x41, 0x22, 0x1C, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x7F, 0x09, 0x09, 0x09, 0x01,
  640. 0x3E, 0x41, 0x49, 0x49, 0x7A, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x41, 0x7F, 0x41, 0x00,
  641. 0x20, 0x40, 0x41, 0x3F, 0x01, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x7F, 0x40, 0x40, 0x40, 0x40,
  642. 0x7F, 0x02, 0x0C, 0x02, 0x7F, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x3E, 0x41, 0x41, 0x41, 0x3E,
  643. 0x7F, 0x09, 0x09, 0x09, 0x06, 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x7F, 0x09, 0x19, 0x29, 0x46,
  644. 0x46, 0x49, 0x49, 0x49, 0x31, 0x01, 0x01, 0x7F, 0x01, 0x01, 0x3F, 0x40, 0x40, 0x40, 0x3F,
  645. 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x63, 0x14, 0x08, 0x14, 0x63,
  646. 0x07, 0x08, 0x70, 0x08, 0x07, 0x61, 0x51, 0x49, 0x45, 0x43, 0x00, 0x7F, 0x41, 0x41, 0x00,
  647. 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x41, 0x41, 0x7F, 0x00, 0x04, 0x02, 0x01, 0x02, 0x04,
  648. 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x01, 0x02, 0x04, 0x00, 0x20, 0x54, 0x54, 0x54, 0x78,
  649. 0x7F, 0x48, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x44, 0x20, 0x38, 0x44, 0x44, 0x48, 0x7F,
  650. 0x38, 0x54, 0x54, 0x54, 0x18, 0x08, 0x7E, 0x09, 0x01, 0x02, 0x18, 0xA4, 0xA4, 0xA4, 0x7C,
  651. 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x44, 0x7D, 0x40, 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00,
  652. 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78,
  653. 0x7C, 0x08, 0x04, 0x04, 0x78, 0x38, 0x44, 0x44, 0x44, 0x38, 0xFC, 0x24, 0x24, 0x24, 0x18,
  654. 0x18, 0x24, 0x24, 0x18, 0xFC, 0x7C, 0x08, 0x04, 0x04, 0x08, 0x48, 0x54, 0x54, 0x54, 0x20,
  655. 0x04, 0x3F, 0x44, 0x40, 0x20, 0x3C, 0x40, 0x40, 0x20, 0x7C, 0x1C, 0x20, 0x40, 0x20, 0x1C,
  656. 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x44, 0x28, 0x10, 0x28, 0x44, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C,
  657. 0x44, 0x64, 0x54, 0x4C, 0x44, 0x08, 0x36, 0x41, 0x41, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00,
  658. 0x00, 0x41, 0x41, 0x36, 0x08, 0x08, 0x04, 0x08, 0x10, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
  659. };
  660. // OLED init settings
  661. const uint8_t OLED_INIT_CMD[] PROGMEM = {
  662. 0xC8, 0xA1, // flip screen
  663. 0xA8, 0x1F, // set multiplex ratio
  664. 0xDA, 0x02, // set com pins hardware configuration
  665. 0x8D, 0x14, // set DC-DC enable
  666. 0xAF // display on
  667. };
  668. // OLED variables
  669. uint8_t OLED_x, OLED_y; // current cursor position
  670. // OLED init function
  671. void OLED_init(void) {
  672. I2C_init(); // initialize I2C first
  673. I2C_start(OLED_ADDR); // start transmission to OLED
  674. I2C_write(OLED_CMD_MODE); // set command mode
  675. for(uint8_t i = 0; i < OLED_INIT_LEN; i++)
  676. I2C_write(pgm_read_byte(&OLED_INIT_CMD[i])); // send the command bytes
  677. I2C_stop(); // stop transmission
  678. }
  679. // OLED set the cursor
  680. void OLED_setCursor(uint8_t xpos, uint8_t ypos) {
  681. I2C_start(OLED_ADDR); // start transmission to OLED
  682. I2C_write(OLED_CMD_MODE); // set command mode
  683. I2C_write(xpos & 0x0F); // set low nibble of start column
  684. I2C_write(0x10 | (xpos >> 4)); // set high nibble of start column
  685. I2C_write(0xB0 | (ypos & 0x07)); // set start page
  686. I2C_stop(); // stop transmission
  687. OLED_x = xpos; OLED_y = ypos; // set the cursor variables
  688. }
  689. // OLED clear line
  690. void OLED_clearLine(uint8_t line) {
  691. OLED_setCursor(0, line); // set cursor to line start
  692. I2C_start(OLED_ADDR); // start transmission to OLED
  693. I2C_write(OLED_DAT_MODE); // set data mode
  694. for(uint8_t i=128; i; i--) I2C_write(0x00); // clear the line
  695. I2C_stop(); // stop transmission
  696. }
  697. // OLED clear screen
  698. void OLED_clearScreen(void) {
  699. for(uint8_t i=0; i<4; i++) // 4 lines
  700. OLED_clearLine(i); // clear line
  701. }
  702. // OLED print a single character
  703. void OLED_printChar(char c) {
  704. uint16_t ptr = c - 32; // character pointer
  705. ptr += ptr << 2; // -> ptr = (ch - 32) * 5;
  706. I2C_write(0x00); // write space between characters
  707. for(uint8_t i=5 ; i; i--) I2C_write(pgm_read_byte(&OLED_FONT[ptr++]));
  708. OLED_x += 6; // update cursor
  709. if(OLED_x > 122) { // line end ?
  710. I2C_stop(); // stop data transmission
  711. OLED_setCursor(0,++OLED_y); // set next line start
  712. I2C_start(OLED_ADDR); // start transmission to OLED
  713. I2C_write(OLED_DAT_MODE); // set data mode
  714. }
  715. }
  716. // OLED print a string from program memory
  717. void OLED_printPrg(const char* p) {
  718. I2C_start(OLED_ADDR); // start transmission to OLED
  719. I2C_write(OLED_DAT_MODE); // set data mode
  720. char ch = pgm_read_byte(p); // read first character from program memory
  721. while(ch) { // repeat until string terminator
  722. OLED_printChar(ch); // print character on OLED
  723. ch = pgm_read_byte(++p); // read next character
  724. }
  725. I2C_stop(); // stop transmission
  726. }
  727. // OLED convert byte nibble into hex character and prints it
  728. void OLED_printNibble(uint8_t nibble) {
  729. char c;
  730. if(nibble <= 9) c = '0' + nibble;
  731. else c = 'A' + nibble - 10;
  732. OLED_printChar(c);
  733. }
  734. // OLED print byte as hex
  735. void OLED_printHex(uint8_t value) {
  736. I2C_start(OLED_ADDR); // start transmission to OLED
  737. I2C_write(OLED_DAT_MODE); // set data mode
  738. OLED_printNibble(value >> 4); // print high nibble
  739. OLED_printNibble(value & 0x0F); // print low nibble
  740. I2C_stop(); // stop transmission
  741. }