Advertisement
Guest User

Untitled

a guest
Nov 21st, 2014
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.80 KB | None | 0 0
  1. /*
  2. Inverse Display
  3.  
  4. Circuit:
  5. * I2C OLED Panel attached to pins SDA, SCL
  6. * Power inputs attached to pins 3V3, +5V,GND,GND,VIN
  7.  
  8. Created 17 Jan 2012
  9. by: Jimbo.we(www.geekonfire.com)
  10.  
  11. */
  12.  
  13. #include <Wire.h>
  14. #include <GOFi2cOLED.h>
  15. #include <avr/pgmspace.h>
  16.  
  17. GOFi2cOLED GOFoled;
  18. #define SDA_PIN 3
  19. #define SDA_PORT PORTD
  20. #define SCL_PIN 2
  21. #define SCL_PORT PORTD
  22. #ifndef _SOFTI2C_H
  23. #define _SOFTI2C_H 1
  24.  
  25. // Init function. Needs to be called once in the beginning.
  26. // Returns false if SDA or SCL are low, which probably means
  27. // a I2C bus lockup or that the lines are not pulled up.+
  28. boolean __attribute__ ((noinline)) i2c_init(void);
  29.  
  30. // Start transfer function: <addr> is the 8-bit I2C address (including the R/W
  31. // bit).
  32. // Return: true if the slave replies with an "acknowledge", false otherwise
  33. bool __attribute__ ((noinline)) i2c_start(uint8_t addr);
  34.  
  35. // Similar to start function, but wait for an ACK! Be careful, this can
  36. // result in an infinite loop!
  37. void __attribute__ ((noinline)) i2c_start_wait(uint8_t addr);
  38.  
  39. // Repeated start function: After having claimed the bus with a start condition,
  40. // you can address another or the same chip again without an intervening
  41. // stop condition.
  42. // Return: true if the slave replies with an "acknowledge", false otherwise
  43. bool __attribute__ ((noinline)) i2c_rep_start(uint8_t addr);
  44.  
  45. // Issue a stop condition, freeing the bus.
  46. void __attribute__ ((noinline)) i2c_stop(void) asm("ass_i2c_stop");
  47.  
  48. // Write one byte to the slave chip that had been addressed
  49. // by the previous start call. <value> is the byte to be sent.
  50. // Return: true if the slave replies with an "acknowledge", false otherwise
  51. bool __attribute__ ((noinline)) i2c_write(uint8_t value) asm("ass_i2c_write");
  52.  
  53. // Read one byte. If <last> is true, we send a NAK after having received
  54. // the byte in order to terminate the read sequence.
  55. uint8_t __attribute__ ((noinline)) i2c_read(bool last);
  56.  
  57. // You can set I2C_CPUFREQ independently of F_CPU if you
  58. // change the CPU frequency on the fly. If do not define it,
  59. // it will use the value of F_CPU
  60. #ifndef I2C_CPUFREQ
  61. #define I2C_CPUFREQ F_CPU
  62. #endif
  63.  
  64. // If I2C_FASTMODE is set to 1, then the highest possible frequency below 400kHz
  65. // is selected. Be aware that not all slave chips may be able to deal with that!
  66. #ifndef I2C_FASTMODE
  67. #define I2C_FASTMODE 0
  68. #endif
  69.  
  70. // If I2C_FASTMODE is not defined or defined to be 0, then you can set
  71. // I2C_SLOWMODE to 1. In this case, the I2C frequency will not be higher
  72. // than 25KHz. This could be useful for problematic buses.
  73. #ifndef I2C_SLOWMODE
  74. #define I2C_SLOWMODE 1
  75. #endif
  76.  
  77. // if I2C_NOINTERRUPT is 1, then the I2C routines are not interruptable.
  78. // This is most probably only necessary if you are using a 1MHz system clock,
  79. // you are communicating with a SMBus device, and you want to avoid timeouts.
  80. // Be aware that the interrupt bit is enabled after each call. So the
  81. // I2C functions should not be called in interrupt routines or critical regions.
  82. #ifndef I2C_NOINTERRUPT
  83. #define I2C_NOINTERRUPT 0
  84. #endif
  85.  
  86. // I2C_TIMEOUT can be set to a value between 1 and 10000.
  87. // If it is defined and nonzero, it leads to a timeout if the
  88. // SCL is low longer than I2C_TIMEOUT milliseconds, i.e., max timeout is 10 sec
  89. #ifndef I2C_TIMEOUT
  90. #define I2C_TIMEOUT 0
  91. #else
  92. #if I2C_TIMEOUT > 10000
  93. #error I2C_TIMEOUT is too large
  94. #endif
  95. #endif
  96.  
  97. #define I2C_TIMEOUT_DELAY_LOOPS (I2C_CPUFREQ/1000UL)*I2C_TIMEOUT/4000UL
  98. #if I2C_TIMEOUT_DELAY_LOOPS < 1
  99. #define I2C_MAX_STRETCH 1
  100. #else
  101. #if I2C_TIMEOUT_DELAY_LOOPS > 60000UL
  102. #define I2C_MAX_STRETCH 60000UL
  103. #else
  104. #define I2C_MAX_STRETCH I2C_TIMEOUT_DELAY_LOOPS
  105. #endif
  106. #endif
  107.  
  108. #if I2C_FASTMODE
  109. #define I2C_DELAY_COUNTER (((I2C_CPUFREQ/400000L)/2-19)/3)
  110. #else
  111. #if I2C_SLOWMODE
  112. #define I2C_DELAY_COUNTER (((I2C_CPUFREQ/12000L)/2-19)/3)
  113. #else
  114. #define I2C_DELAY_COUNTER (((I2C_CPUFREQ/6000L)/2-19)/3)
  115. #endif
  116. #endif
  117.  
  118. // Table of I2C bus speed in kbit/sec:
  119. // CPU clock: 1MHz 2MHz 4MHz 8MHz 16MHz 20MHz
  120. // Fast I2C mode 40 80 150 300 400 400
  121. // Standard I2C mode 40 80 100 100 100 100
  122. // Slow I2C mode 25 25 25 25 25 25
  123.  
  124. // constants for reading & writing
  125. #define I2C_READ 1
  126. #define I2C_WRITE 0
  127.  
  128. // map the IO register back into the IO address space
  129. #define SDA_DDR (_SFR_IO_ADDR(SDA_PORT) - 1)
  130. #define SCL_DDR (_SFR_IO_ADDR(SCL_PORT) - 1)
  131. #define SDA_OUT _SFR_IO_ADDR(SDA_PORT)
  132. #define SCL_OUT _SFR_IO_ADDR(SCL_PORT)
  133. #define SDA_IN (_SFR_IO_ADDR(SDA_PORT) - 2)
  134. #define SCL_IN (_SFR_IO_ADDR(SCL_PORT) - 2)
  135.  
  136. #ifndef __tmp_reg__
  137. #define __tmp_reg__ 0
  138. #endif
  139.  
  140.  
  141. // Internal delay functions.
  142. void __attribute__ ((noinline)) i2c_delay_half(void) asm("ass_i2c_delay_half");
  143. void __attribute__ ((noinline)) i2c_wait_scl_high(void) asm("ass_i2c_wait_scl_high");
  144.  
  145. void i2c_delay_half(void)
  146. { // function call 3 cycles => 3C
  147. #if I2C_DELAY_COUNTER < 1
  148. __asm__ __volatile__ (" ret");
  149. // 7 cycles for call and return
  150. #else
  151. __asm__ __volatile__
  152. (
  153. " ldi r25, %[DELAY] ;load delay constant ;; 4C \n\t"
  154. "_Lidelay: \n\t"
  155. " dec r25 ;decrement counter ;; 4C+xC \n\t"
  156. " brne _Lidelay ;;5C+(x-1)2C+xC\n\t"
  157. " ret ;; 9C+(x-1)2C+xC = 7C+xC"
  158. : : [DELAY] "M" I2C_DELAY_COUNTER : "r25");
  159. // 7 cycles + 3 times x cycles
  160. #endif
  161. }
  162.  
  163. void i2c_wait_scl_high(void)
  164. {
  165. #if I2C_TIMEOUT <= 0
  166. __asm__ __volatile__
  167. ("_Li2c_wait_stretch: \n\t"
  168. " sbis %[SCLIN],%[SCLPIN] ;wait for SCL high \n\t"
  169. " rjmp _Li2c_wait_stretch \n\t"
  170. " cln ;signal: no timeout \n\t"
  171. " ret "
  172. : : [SCLIN] "I" (SCL_IN), [SCLPIN] "I" (SCL_PIN));
  173. #else
  174. __asm__ __volatile__
  175. ( " ldi r27, %[HISTRETCH] ;load delay counter \n\t"
  176. " ldi r26, %[LOSTRETCH] \n\t"
  177. "_Lwait_stretch: \n\t"
  178. " clr __tmp_reg__ ;do next loop 255 times \n\t"
  179. "_Lwait_stretch_inner_loop: \n\t"
  180. " rcall _Lcheck_scl_level ;call check function ;; 12C \n\t"
  181. " brpl _Lstretch_done ;done if N=0 ;; +1 = 13C\n\t"
  182. " dec __tmp_reg__ ;dec inner loop counter;; +1 = 14C\n\t"
  183. " brne _Lwait_stretch_inner_loop ;; +2 = 16C\n\t"
  184. " sbiw r26,1 ;dec outer loop counter \n\t"
  185. " brne _Lwait_stretch ;continue with outer loop \n\t"
  186. " sen ;timeout -> set N-bit=1 \n\t"
  187. " rjmp _Lwait_return ;and return with N=1\n\t"
  188. "_Lstretch_done: ;SCL=1 sensed \n\t"
  189. " cln ;OK -> clear N-bit \n\t"
  190. " rjmp _Lwait_return ; and return with N=0 \n\t"
  191.  
  192. "_Lcheck_scl_level: ;; call = 3C\n\t"
  193. " cln ;; +1C = 4C \n\t"
  194. " sbic %[SCLIN],%[SCLPIN] ;skip if SCL still low ;; +2C = 6C \n\t"
  195. " rjmp _Lscl_high ;; +0C = 6C \n\t"
  196. " sen ;; +1 = 7C\n\t "
  197. "_Lscl_high: "
  198. " nop ;; +1C = 8C \n\t"
  199. " ret ;return N-Bit=1 if low ;; +4 = 12C\n\t"
  200.  
  201. "_Lwait_return:"
  202. : : [SCLIN] "I" (SCL_IN), [SCLPIN] "I" (SCL_PIN),
  203. [HISTRETCH] "M" (I2C_MAX_STRETCH>>8),
  204. [LOSTRETCH] "M" (I2C_MAX_STRETCH&0xFF)
  205. : "r26", "r27");
  206. #endif
  207. }
  208.  
  209.  
  210. boolean i2c_init(void)
  211. {
  212. __asm__ __volatile__
  213. (" cbi %[SDADDR],%[SDAPIN] ;release SDA \n\t"
  214. " cbi %[SCLDDR],%[SCLPIN] ;release SCL \n\t"
  215. " cbi %[SDAOUT],%[SDAPIN] ;clear SDA output value \n\t"
  216. " cbi %[SCLOUT],%[SCLPIN] ;clear SCL output value \n\t"
  217. " clr r24 ;set return value to false \n\t"
  218. " clr r25 ;set return value to false \n\t"
  219. " sbis %[SDAIN],%[SDAPIN] ;check for SDA high\n\t"
  220. " ret ;if low return with false \n\t"
  221. " sbis %[SCLIN],%[SCLPIN] ;check for SCL high \n\t"
  222. " ret ;if low return with false \n\t"
  223. " ldi r24,1 ;set return value to true \n\t"
  224. " ret "
  225. : :
  226. [SCLDDR] "I" (SCL_DDR), [SCLPIN] "I" (SCL_PIN),
  227. [SCLIN] "I" (SCL_IN), [SCLOUT] "I" (SCL_OUT),
  228. [SDADDR] "I" (SDA_DDR), [SDAPIN] "I" (SDA_PIN),
  229. [SDAIN] "I" (SDA_IN), [SDAOUT] "I" (SDA_OUT));
  230. return true;
  231. }
  232.  
  233. bool i2c_start(uint8_t addr)
  234. {
  235. __asm__ __volatile__
  236. (
  237. #if I2C_NOINTERRUPT
  238. " cli ;clear IRQ bit \n\t"
  239. #endif
  240. " sbis %[SCLIN],%[SCLPIN] ;check for clock stretching slave\n\t"
  241. " rcall ass_i2c_wait_scl_high ;wait until SCL=H\n\t"
  242. " sbi %[SDADDR],%[SDAPIN] ;force SDA low \n\t"
  243. " rcall ass_i2c_delay_half ;wait T/2 \n\t"
  244. " rcall ass_i2c_write ;now write address \n\t"
  245. " ret"
  246. : : [SDADDR] "I" (SDA_DDR), [SDAPIN] "I" (SDA_PIN),
  247. [SCLIN] "I" (SCL_IN),[SCLPIN] "I" (SCL_PIN));
  248. return true; // we never return here!
  249. }
  250.  
  251. bool i2c_rep_start(uint8_t addr)
  252. {
  253. __asm__ __volatile__
  254.  
  255. (
  256. #if I2C_NOINTERRUPT
  257. " cli \n\t"
  258. #endif
  259. " sbi %[SCLDDR],%[SCLPIN] ;force SCL low \n\t"
  260. " rcall ass_i2c_delay_half ;delay T/2 \n\t"
  261. " cbi %[SDADDR],%[SDAPIN] ;release SDA \n\t"
  262. " rcall ass_i2c_delay_half ;delay T/2 \n\t"
  263. " cbi %[SCLDDR],%[SCLPIN] ;release SCL \n\t"
  264. " rcall ass_i2c_delay_half ;delay T/2 \n\t"
  265. " sbis %[SCLIN],%[SCLPIN] ;check for clock stretching slave\n\t"
  266. " rcall ass_i2c_wait_scl_high ;wait until SCL=H\n\t"
  267. " sbi %[SDADDR],%[SDAPIN] ;force SDA low \n\t"
  268. " rcall ass_i2c_delay_half ;delay T/2 \n\t"
  269. " rcall ass_i2c_write \n\t"
  270. " ret"
  271. : : [SCLDDR] "I" (SCL_DDR), [SCLPIN] "I" (SCL_PIN),[SCLIN] "I" (SCL_IN),
  272. [SDADDR] "I" (SDA_DDR), [SDAPIN] "I" (SDA_PIN));
  273. return true; // just to fool the compiler
  274. }
  275.  
  276. void i2c_start_wait(uint8_t addr)
  277. {
  278. __asm__ __volatile__
  279. (
  280. " push r24 ;save original parameter \n\t"
  281. "_Li2c_start_wait1: \n\t"
  282. " pop r24 ;restore original parameter\n\t"
  283. " push r24 ;and save again \n\t"
  284. #if I2C_NOINTERRUPT
  285. " cli ;disable interrupts \n\t"
  286. #endif
  287. " sbis %[SCLIN],%[SCLPIN] ;check for clock stretching slave\n\t"
  288. " rcall ass_i2c_wait_scl_high ;wait until SCL=H\n\t"
  289. " sbi %[SDADDR],%[SDAPIN] ;force SDA low \n\t"
  290. " rcall ass_i2c_delay_half ;delay T/2 \n\t"
  291. " rcall ass_i2c_write ;write address \n\t"
  292. " tst r24 ;if device not busy -> done \n\t"
  293. " brne _Li2c_start_wait_done \n\t"
  294. " rcall ass_i2c_stop ;terminate write & enable IRQ \n\t"
  295. " rjmp _Li2c_start_wait1 ;device busy, poll ack again \n\t"
  296. "_Li2c_start_wait_done: \n\t"
  297. " pop __tmp_reg__ ;pop off orig argument \n\t"
  298. " ret "
  299. : : [SDADDR] "I" (SDA_DDR), [SDAPIN] "I" (SDA_PIN),
  300. [SCLIN] "I" (SCL_IN),[SCLPIN] "I" (SCL_PIN));
  301. }
  302.  
  303. void i2c_stop(void)
  304. {
  305. __asm__ __volatile__
  306. (
  307. " sbi %[SCLDDR],%[SCLPIN] ;force SCL low \n\t"
  308. " sbi %[SDADDR],%[SDAPIN] ;force SDA low \n\t"
  309. " rcall ass_i2c_delay_half ;T/2 delay \n\t"
  310. " cbi %[SCLDDR],%[SCLPIN] ;release SCL \n\t"
  311. " rcall ass_i2c_delay_half ;T/2 delay \n\t"
  312. " sbis %[SCLIN],%[SCLPIN] ;check for clock stretching slave\n\t"
  313. " rcall ass_i2c_wait_scl_high ;wait until SCL=H\n\t"
  314. " cbi %[SDADDR],%[SDAPIN] ;release SDA \n\t"
  315. " rcall ass_i2c_delay_half \n\t"
  316. #if I2C_NOINTERRUPT
  317. " sei ;enable interrupts again!\n\t"
  318. #endif
  319. : : [SCLDDR] "I" (SCL_DDR), [SCLPIN] "I" (SCL_PIN), [SCLIN] "I" (SCL_IN),
  320. [SDADDR] "I" (SDA_DDR), [SDAPIN] "I" (SDA_PIN));
  321. }
  322.  
  323. bool i2c_write(uint8_t value)
  324. {
  325. __asm__ __volatile__
  326. (
  327. " sec ;set carry flag \n\t"
  328. " rol r24 ;shift in carry and shift out MSB \n\t"
  329. " rjmp _Li2c_write_first \n\t"
  330. "_Li2c_write_bit:\n\t"
  331. " lsl r24 ;left shift into carry ;; 1C\n\t"
  332. "_Li2c_write_first:\n\t"
  333. " breq _Li2c_get_ack ;jump if TXreg is empty;; +1 = 2C \n\t"
  334. " sbi %[SCLDDR],%[SCLPIN] ;force SCL low ;; +2 = 4C \n\t"
  335. " nop \n\t"
  336. " nop \n\t"
  337. " nop \n\t"
  338. " brcc _Li2c_write_low ;;+1/+2=5/6C\n\t"
  339. " nop ;; +1 = 7C \n\t"
  340. " cbi %[SDADDR],%[SDAPIN] ;release SDA ;; +2 = 9C \n\t"
  341. " rjmp _Li2c_write_high ;; +2 = 11C \n\t"
  342. "_Li2c_write_low: \n\t"
  343. " sbi %[SDADDR],%[SDAPIN] ;force SDA low ;; +2 = 9C \n\t"
  344. " rjmp _Li2c_write_high ;;+2 = 11C \n\t"
  345. "_Li2c_write_high: \n\t"
  346. #if I2C_DELAY_COUNTER >= 1
  347. " rcall ass_i2c_delay_half ;delay T/2 ;;+X = 11C+X\n\t"
  348. #endif
  349. " cbi %[SCLDDR],%[SCLPIN] ;release SCL ;;+2 = 13C+X\n\t"
  350. " cln ;clear N-bit ;;+1 = 14C+X\n\t"
  351. " nop \n\t"
  352. " nop \n\t"
  353. " nop \n\t"
  354. " sbis %[SCLIN],%[SCLPIN] ;check for SCL high ;;+2 = 16C+X\n\t"
  355. " rcall ass_i2c_wait_scl_high \n\t"
  356. " brpl _Ldelay_scl_high ;;+2 = 18C+X\n\t"
  357. "_Li2c_write_return_false: \n\t"
  358. " clr r24 ; return false because of timeout \n\t"
  359. " rjmp _Li2c_write_return \n\t"
  360. "_Ldelay_scl_high: \n\t"
  361. #if I2C_DELAY_COUNTER >= 1
  362. " rcall ass_i2c_delay_half ;delay T/2 ;;+X= 18C+2X\n\t"
  363. #endif
  364. " rjmp _Li2c_write_bit \n\t"
  365. " ;; +2 = 20C +2X for one bit-loop \n\t"
  366. "_Li2c_get_ack: \n\t"
  367. " sbi %[SCLDDR],%[SCLPIN] ;force SCL low ;; +2 = 5C \n\t"
  368. " nop \n\t"
  369. " nop \n\t"
  370. " cbi %[SDADDR],%[SDAPIN] ;release SDA ;;+2 = 7C \n\t"
  371. #if I2C_DELAY_COUNTER >= 1
  372. " rcall ass_i2c_delay_half ;delay T/2 ;; +X = 7C+X \n\t"
  373. #endif
  374. " clr r25 ;; 17C+2X \n\t"
  375. " clr r24 ;return 0 ;; 14C + X \n\t"
  376. " cbi %[SCLDDR],%[SCLPIN] ;release SCL ;; +2 = 9C+X\n\t"
  377. "_Li2c_ack_wait: \n\t"
  378. " cln ; clear N-bit ;; 10C + X\n\t"
  379. " nop \n\t"
  380. " sbis %[SCLIN],%[SCLPIN] ;wait SCL high ;; 12C + X \n\t"
  381. " rcall ass_i2c_wait_scl_high \n\t"
  382. " brmi _Li2c_write_return_false ;; 13C + X \n\t "
  383. " sbis %[SDAIN],%[SDAPIN] ;if SDA hi -> return 0 ;; 15C + X \n\t"
  384. " ldi r24,1 ;return true ;; 16C + X \n\t"
  385. #if I2C_DELAY_COUNTER >= 1
  386. " rcall ass_i2c_delay_half ;delay T/2 ;; 16C + 2X \n\t"
  387. #endif
  388. "_Li2c_write_return: \n\t"
  389. " nop \n\t "
  390. " nop \n\t "
  391. " sbi %[SCLDDR],%[SCLPIN] ;force SCL low so SCL=H is short\n\t"
  392. " ret \n\t"
  393. " ;; + 4 = 17C + 2X for acknowldge bit"
  394. ::
  395. [SCLDDR] "I" (SCL_DDR), [SCLPIN] "I" (SCL_PIN), [SCLIN] "I" (SCL_IN),
  396. [SDADDR] "I" (SDA_DDR), [SDAPIN] "I" (SDA_PIN), [SDAIN] "I" (SDA_IN));
  397. return true; // fooling the compiler
  398. }
  399.  
  400. uint8_t i2c_read(bool last)
  401. {
  402. __asm__ __volatile__
  403. (
  404. " ldi r23,0x01 \n\t"
  405. "_Li2c_read_bit: \n\t"
  406. " sbi %[SCLDDR],%[SCLPIN] ;force SCL low ;; 2C \n\t"
  407. " cbi %[SDADDR],%[SDAPIN] ;release SDA(prev. ACK);; 4C \n\t"
  408. " nop \n\t"
  409. " nop \n\t"
  410. " nop \n\t"
  411. #if I2C_DELAY_COUNTER >= 1
  412. " rcall ass_i2c_delay_half ;delay T/2 ;; 4C+X \n\t"
  413. #endif
  414. " cbi %[SCLDDR],%[SCLPIN] ;release SCL ;; 6C + X \n\t"
  415. #if I2C_DELAY_COUNTER >= 1
  416. " rcall ass_i2c_delay_half ;delay T/2 ;; 6C + 2X \n\t"
  417. #endif
  418. " cln ; clear N-bit ;; 7C + 2X \n\t"
  419. " nop \n\t "
  420. " nop \n\t "
  421. " nop \n\t "
  422. " sbis %[SCLIN], %[SCLPIN] ;check for SCL high ;; 9C +2X \n\t"
  423. " rcall ass_i2c_wait_scl_high \n\t"
  424. " brmi _Li2c_read_return ;return if timeout ;; 10C + 2X\n\t"
  425. " clc ;clear carry flag ;; 11C + 2X\n\t"
  426. " sbic %[SDAIN],%[SDAPIN] ;if SDA is high ;; 11C + 2X\n\t"
  427. " sec ;set carry flag ;; 12C + 2X\n\t"
  428. " rol r23 ;store bit ;; 13C + 2X\n\t"
  429. " brcc _Li2c_read_bit ;while receiv reg not full \n\t"
  430. " ;; 15C + 2X for one bit loop \n\t"
  431.  
  432. "_Li2c_put_ack: \n\t"
  433. " sbi %[SCLDDR],%[SCLPIN] ;force SCL low ;; 2C \n\t"
  434. " cpi r24,0 ;; 3C \n\t"
  435. " breq _Li2c_put_ack_low ;if (ack=0) ;; 5C \n\t"
  436. " cbi %[SDADDR],%[SDAPIN] ;release SDA \n\t"
  437. " rjmp _Li2c_put_ack_high \n\t"
  438. "_Li2c_put_ack_low: ;else \n\t"
  439. " sbi %[SDADDR],%[SDAPIN] ;force SDA low ;; 7C \n\t"
  440. "_Li2c_put_ack_high: \n\t"
  441. " nop \n\t "
  442. " nop \n\t "
  443. " nop \n\t "
  444. #if I2C_DELAY_COUNTER >= 1
  445. " rcall ass_i2c_delay_half ;delay T/2 ;; 7C + X \n\t"
  446. #endif
  447. " cbi %[SCLDDR],%[SCLPIN] ;release SCL ;; 9C +X \n\t"
  448. " cln ;clear N ;; +1 = 10C\n\t"
  449. " nop \n\t "
  450. " nop \n\t "
  451. " sbis %[SCLIN],%[SCLPIN] ;wait SCL high ;; 12C + X\n\t"
  452. " rcall ass_i2c_wait_scl_high \n\t"
  453. #if I2C_DELAY_COUNTER >= 1
  454. " rcall ass_i2c_delay_half ;delay T/2 ;; 11C + 2X\n\t"
  455. #endif
  456. "_Li2c_read_return: \n\t"
  457. " nop \n\t "
  458. " nop \n\t "
  459. "sbi %[SCLDDR],%[SCLPIN] ;force SCL low so SCL=H is short\n\t"
  460. " mov r24,r23 ;; 12C + 2X \n\t"
  461. " clr r25 ;; 13 C + 2X\n\t"
  462. " ret ;; 17C + X"
  463. ::
  464. [SCLDDR] "I" (SCL_DDR), [SCLPIN] "I" (SCL_PIN), [SCLIN] "I" (SCL_IN),
  465. [SDADDR] "I" (SDA_DDR), [SDAPIN] "I" (SDA_PIN), [SDAIN] "I" (SDA_IN)
  466. );
  467. return ' '; // fool the compiler!
  468. }
  469.  
  470. #endif
  471. byte deviceAddress = 11;
  472.  
  473.  
  474. #define VOLTAGE 0x09
  475. #define TEMPERATURE 0x08
  476. #define CURRENT 0x0a
  477. #define CAPACITY 0x10
  478. #define CHARGE_CURRENT 0x14
  479. #define CHARGE_VOLTAGE 0x15
  480. #define TIME_TO_FULL 0x13
  481. #define TIME_TO_EMPTY 0x11
  482. #define CHARGE 0x0d
  483.  
  484. int fetchWord(byte func)
  485. {
  486. i2c_start(deviceAddress<<1 | I2C_WRITE);
  487. delay(5);
  488. i2c_write(func);
  489. i2c_rep_start(deviceAddress<<1 | I2C_READ);
  490.  
  491.  
  492.  
  493. byte b1 = i2c_read(false);
  494. byte b2 = i2c_read(true);
  495. i2c_stop();
  496. return (int)b1|((( int)b2)<<8);
  497. }
  498.  
  499. void setup()
  500. {
  501. pinMode(8,INPUT_PULLUP);
  502. pinMode(7,INPUT_PULLUP);
  503. GOFoled.init(0x3C); //initialze OLED display,default slave address is 0x3D
  504.  
  505. }
  506.  
  507. void loop()
  508. {
  509. delay(100);
  510. GOFoled.clearDisplay();
  511.  
  512. GOFoled.setTextSize(1);
  513. GOFoled.setTextColor(WHITE);
  514. GOFoled.setCursor(0,16);
  515. GOFoled.print("Voltaggio: ");
  516. GOFoled.print(((float)fetchWord(VOLTAGE))/1000.0f);
  517. GOFoled.println(" V");
  518. long current = (fetchWord(CURRENT));
  519. if ( current <= 0 )
  520. {
  521. GOFoled.print("Assorbimento: ");
  522. GOFoled.print(-current);
  523. GOFoled.println("mA");
  524. GOFoled.print("Rim: ");
  525. long t = fetchWord(TIME_TO_EMPTY);
  526. if ( t > 60*24 )
  527. {
  528. GOFoled.print(t/(60*24));
  529. GOFoled.println(" giorni");
  530. }
  531. else if ( t > 120 )
  532. {
  533. GOFoled.print(t/60);
  534. GOFoled.println(" ore");
  535. }else{
  536. GOFoled.print(t);
  537. GOFoled.println(" minuti");
  538. }
  539.  
  540. }else{
  541. GOFoled.print("Corrente di carica: ");
  542. GOFoled.print(current);
  543. GOFoled.println("mA");
  544. GOFoled.print("Rim: ");
  545. long t = fetchWord(TIME_TO_FULL);
  546. if ( t > 60*24 )
  547. {
  548. GOFoled.print(t/(60*24));
  549. GOFoled.println(" giorni");
  550. }
  551. else if ( t > 120 )
  552. {
  553. GOFoled.print(t/60);
  554. GOFoled.println(" ore");
  555. }else{
  556. GOFoled.print(t);
  557. GOFoled.println(" minuti");
  558. }
  559. }
  560. GOFoled.print("Carica:");
  561. GOFoled.print(fetchWord(CHARGE));
  562. GOFoled.print("% T:");
  563. GOFoled.print(((float)fetchWord(TEMPERATURE))/10.0-273.15);
  564. GOFoled.print(" C");
  565. GOFoled.display();
  566.  
  567. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement