Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

407 lines
12 KiB

7 years ago
  1. /*
  2. I2C MODULE
  3. Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
  4. */
  5. #if I2C_SUPPORT
  6. unsigned int _i2c_locked[16] = {0};
  7. #if I2C_USE_BRZO
  8. unsigned long _i2c_scl_frequency = 0;
  9. #endif
  10. // -----------------------------------------------------------------------------
  11. // Private
  12. // -----------------------------------------------------------------------------
  13. int _i2cGetSDA() {
  14. return getSetting("i2cSDA", I2C_SDA_PIN);
  15. }
  16. int _i2cGetSCL() {
  17. return getSetting("i2cSCL", I2C_SCL_PIN);
  18. }
  19. int _i2cClearbus(int sda, int scl) {
  20. #if defined(TWCR) && defined(TWEN)
  21. // Disable the Atmel 2-Wire interface so we can control the SDA and SCL pins directly
  22. TWCR &= ~(_BV(TWEN));
  23. #endif
  24. // Make SDA (data) and SCL (clock) pins inputs with pullup
  25. pinMode(sda, INPUT_PULLUP);
  26. pinMode(scl, INPUT_PULLUP);
  27. nice_delay(2500);
  28. // Wait 2.5 secs. This is strictly only necessary on the first power
  29. // up of the DS3231 module to allow it to initialize properly,
  30. // but is also assists in reliable programming of FioV3 boards as it gives the
  31. // IDE a chance to start uploaded the program
  32. // before existing sketch confuses the IDE by sending Serial data.
  33. // If it is held low the device cannot become the I2C master
  34. // I2C bus error. Could not clear SCL clock line held low
  35. boolean scl_low = (digitalRead(scl) == LOW);
  36. if (scl_low) return 1;
  37. boolean sda_low = (digitalRead(sda) == LOW);
  38. int clockCount = 20; // > 2x9 clock
  39. // While SDA is low for at most 20 cycles
  40. while (sda_low && (clockCount > 0)) {
  41. clockCount--;
  42. // Note: I2C bus is open collector so do NOT drive SCL or SDA high
  43. pinMode(scl, INPUT); // release SCL pullup so that when made output it will be LOW
  44. pinMode(scl, OUTPUT); // then clock SCL Low
  45. delayMicroseconds(10); // for >5uS
  46. pinMode(scl, INPUT); // release SCL LOW
  47. pinMode(scl, INPUT_PULLUP); // turn on pullup resistors again
  48. // do not force high as slave may be holding it low for clock stretching
  49. delayMicroseconds(10); // The >5uS is so that even the slowest I2C devices are handled
  50. // loop waiting for SCL to become high only wait 2sec
  51. scl_low = (digitalRead(scl) == LOW);
  52. int counter = 20;
  53. while (scl_low && (counter > 0)) {
  54. counter--;
  55. nice_delay(100);
  56. scl_low = (digitalRead(scl) == LOW);
  57. }
  58. // If still low after 2 sec error
  59. // I2C bus error. Could not clear. SCL clock line held low by slave clock stretch for >2sec
  60. if (scl_low) return 2;
  61. sda_low = (digitalRead(sda) == LOW); // and check SDA input again and loop
  62. }
  63. // If still low
  64. // I2C bus error. Could not clear. SDA data line held low
  65. if (sda_low) return 3;
  66. // Pull SDA line low for "start" or "repeated start"
  67. pinMode(sda, INPUT); // remove pullup
  68. pinMode(sda, OUTPUT); // and then make it LOW i.e. send an I2C Start or Repeated start control
  69. // When there is only one I2C master a "start" or "repeat start" has the same function as a "stop" and clears the bus
  70. // A Repeat Start is a Start occurring after a Start with no intervening Stop.
  71. delayMicroseconds(10); // wait >5uS
  72. pinMode(sda, INPUT); // remove output low
  73. pinMode(sda, INPUT_PULLUP); // and make SDA high i.e. send I2C STOP control.
  74. delayMicroseconds(10); // wait >5uS
  75. pinMode(sda, INPUT); // and reset pins as tri-state inputs which is the default state on reset
  76. pinMode(scl, INPUT);
  77. // Everything OK
  78. return 0;
  79. }
  80. // ---------------------------------------------------------------------
  81. // I2C API
  82. // ---------------------------------------------------------------------
  83. #if I2C_USE_BRZO
  84. void i2c_wakeup(uint8_t address) {
  85. brzo_i2c_start_transaction(_address, _i2c_scl_frequency);
  86. brzo_i2c_end_transaction();
  87. }
  88. uint8_t i2c_write_uint8(uint8_t address, uint8_t value) {
  89. uint8_t buffer[1] = {value};
  90. brzo_i2c_start_transaction(_address, _i2c_scl_frequency);
  91. brzo_i2c_write_uint8(buffer, 1, false);
  92. return brzo_i2c_end_transaction();
  93. }
  94. uint8_t i2c_write_buffer(uint8_t address, uint8_t * buffer, size_t len) {
  95. brzo_i2c_start_transaction(_address, _i2c_scl_frequency);
  96. brzo_i2c_write_uint8(buffer, len, false);
  97. return brzo_i2c_end_transaction();
  98. }
  99. uint8_t i2c_read_uint8(uint8_t address) {
  100. uint8_t buffer[1] = {reg};
  101. brzo_i2c_start_transaction(_address, _i2c_scl_frequency);
  102. brzo_i2c_read(buffer, 1, false);
  103. brzo_i2c_end_transaction();
  104. return buffer[0];
  105. };
  106. uint8_t i2c_read_uint8(uint8_t address, uint8_t reg) {
  107. uint8_t buffer[1] = {reg};
  108. brzo_i2c_start_transaction(_address, _i2c_scl_frequency);
  109. brzo_i2c_write_uint8(buffer, 1, false);
  110. brzo_i2c_read(buffer, 1, false);
  111. brzo_i2c_end_transaction();
  112. return buffer[0];
  113. };
  114. uint16_t i2c_read_uint16(uint8_t address) {
  115. uint8_t buffer[2] = {reg, 0};
  116. brzo_i2c_start_transaction(_address, _i2c_scl_frequency);
  117. brzo_i2c_read(buffer, 2, false);
  118. brzo_i2c_end_transaction();
  119. return (buffer[0] * 256) | buffer[1];
  120. };
  121. uint16_t i2c_read_uint16(uint8_t address, uint8_t reg) {
  122. uint8_t buffer[2] = {reg, 0};
  123. brzo_i2c_start_transaction(_address, _i2c_scl_frequency);
  124. brzo_i2c_write_uint8(buffer, 1, false);
  125. brzo_i2c_read(buffer, 2, false);
  126. brzo_i2c_end_transaction();
  127. return (buffer[0] * 256) | buffer[1];
  128. };
  129. void i2c_read_buffer(uint8_t address, uint8_t * buffer, size_t len) {
  130. brzo_i2c_start_transaction(address, _i2c_scl_frequency);
  131. brzo_i2c_read(buffer, len, false);
  132. brzo_i2c_end_transaction();
  133. }
  134. #else // not I2C_USE_BRZO
  135. void i2c_wakeup(uint8_t address) {
  136. Wire.beginTransmission((uint8_t) address);
  137. Wire.endTransmission();
  138. }
  139. uint8_t i2c_write_uint8(uint8_t address, uint8_t value) {
  140. Wire.beginTransmission((uint8_t) address);
  141. Wire.write((uint8_t) value);
  142. return Wire.endTransmission();
  143. }
  144. uint8_t i2c_write_buffer(uint8_t address, uint8_t * buffer, size_t len) {
  145. Wire.beginTransmission((uint8_t) address);
  146. Wire.write(buffer, len);
  147. return Wire.endTransmission();
  148. }
  149. uint8_t i2c_read_uint8(uint8_t address) {
  150. uint8_t value;
  151. Wire.beginTransmission((uint8_t) address);
  152. Wire.requestFrom((uint8_t) address, (uint8_t) 1);
  153. value = Wire.read();
  154. Wire.endTransmission();
  155. return value;
  156. };
  157. uint8_t i2c_read_uint8(uint8_t address, uint8_t reg) {
  158. uint8_t value;
  159. Wire.beginTransmission((uint8_t) address);
  160. Wire.write((uint8_t) reg);
  161. Wire.endTransmission();
  162. Wire.requestFrom((uint8_t) address, (uint8_t) 1);
  163. value = Wire.read();
  164. Wire.endTransmission();
  165. return value;
  166. };
  167. uint16_t i2c_read_uint16(uint8_t address) {
  168. uint16_t value;
  169. Wire.beginTransmission((uint8_t) address);
  170. Wire.requestFrom((uint8_t) address, (uint8_t) 2);
  171. value = (Wire.read() * 256) | Wire.read();
  172. Wire.endTransmission();
  173. return value;
  174. };
  175. uint16_t i2c_read_uint16(uint8_t address, uint8_t reg) {
  176. uint16_t value;
  177. Wire.beginTransmission((uint8_t) address);
  178. Wire.write((uint8_t) reg);
  179. Wire.endTransmission();
  180. Wire.requestFrom((uint8_t) address, (uint8_t) 2);
  181. value = (Wire.read() * 256) | Wire.read();
  182. Wire.endTransmission();
  183. return value;
  184. };
  185. void i2c_read_buffer(uint8_t address, uint8_t * buffer, size_t len) {
  186. Wire.beginTransmission((uint8_t) address);
  187. Wire.requestFrom(address, (uint8_t) len);
  188. for (size_t i=0; i<len; i++) buffer[i] = Wire.read();
  189. Wire.endTransmission();
  190. }
  191. #endif // I2C_USE_BRZO
  192. uint8_t i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value) {
  193. uint8_t buffer[2] = {reg, value};
  194. return i2c_write_buffer(address, buffer, 2);
  195. }
  196. uint8_t i2c_write_uint8(uint8_t address, uint8_t reg, uint8_t value1, uint8_t value2) {
  197. uint8_t buffer[3] = {reg, value1, value2};
  198. return i2c_write_buffer(address, buffer, 3);
  199. }
  200. uint8_t i2c_write_uint16(uint8_t address, uint8_t reg, uint16_t value) {
  201. uint8_t buffer[3];
  202. buffer[0] = reg;
  203. buffer[1] = (value >> 8) & 0xFF;
  204. buffer[2] = (value >> 0) & 0xFF;
  205. return i2c_write_buffer(address, buffer, 3);
  206. }
  207. uint8_t i2c_write_uint16(uint8_t address, uint16_t value) {
  208. uint8_t buffer[2];
  209. buffer[0] = (value >> 8) & 0xFF;
  210. buffer[1] = (value >> 0) & 0xFF;
  211. return i2c_write_buffer(address, buffer, 2);
  212. }
  213. uint16_t i2c_read_uint16_le(uint8_t address, uint8_t reg) {
  214. uint16_t temp = i2c_read_uint16(address, reg);
  215. return (temp / 256) | (temp * 256);
  216. };
  217. int16_t i2c_read_int16(uint8_t address, uint8_t reg) {
  218. return (int16_t) i2c_read_uint16(address, reg);
  219. };
  220. int16_t i2c_read_int16_le(uint8_t address, uint8_t reg) {
  221. return (int16_t) i2c_read_uint16_le(address, reg);
  222. };
  223. // -----------------------------------------------------------------------------
  224. // Utils
  225. // -----------------------------------------------------------------------------
  226. void i2cClearBus() {
  227. DEBUG_MSG_P(
  228. PSTR("[I2C] Clear bus (response: %d)\n"),
  229. _i2cClearbus(_i2cGetSDA(), _i2cGetSCL())
  230. );
  231. }
  232. bool i2cCheck(unsigned char address) {
  233. #if I2C_USE_BRZO
  234. brzo_i2c_start_transaction(address, _i2c_scl_frequency);
  235. brzo_i2c_ACK_polling(1000);
  236. return brzo_i2c_end_transaction();
  237. #else
  238. Wire.beginTransmission(address);
  239. return Wire.endTransmission();
  240. #endif
  241. }
  242. bool i2cGetLock(unsigned char address) {
  243. unsigned char index = address / 8;
  244. unsigned char mask = 1 << (address % 8);
  245. if (_i2c_locked[index] & mask) return false;
  246. _i2c_locked[index] = _i2c_locked[index] | mask;
  247. DEBUG_MSG_P(PSTR("[I2C] Address 0x%02X locked\n"), address);
  248. return true;
  249. }
  250. bool i2cReleaseLock(unsigned char address) {
  251. unsigned char index = address / 8;
  252. unsigned char mask = 1 << (address % 8);
  253. if (_i2c_locked[index] & mask) {
  254. _i2c_locked[index] = _i2c_locked[index] & ~mask;
  255. return true;
  256. }
  257. return false;
  258. }
  259. unsigned char i2cFind(size_t size, unsigned char * addresses, unsigned char &start) {
  260. for (unsigned char i=start; i<size; i++) {
  261. if (i2cCheck(addresses[i]) == 0) {
  262. start = i;
  263. return addresses[i];
  264. }
  265. }
  266. return 0;
  267. }
  268. unsigned char i2cFind(size_t size, unsigned char * addresses) {
  269. unsigned char start = 0;
  270. return i2cFind(size, addresses, start);
  271. }
  272. unsigned char i2cFindAndLock(size_t size, unsigned char * addresses) {
  273. unsigned char start = 0;
  274. unsigned char address = 0;
  275. while ((address = i2cFind(size, addresses, start))) {
  276. if (i2cGetLock(address)) break;
  277. start++;
  278. }
  279. return address;
  280. }
  281. void i2cScan() {
  282. unsigned char nDevices = 0;
  283. for (unsigned char address = 1; address < 127; address++) {
  284. unsigned char error = i2cCheck(address);
  285. if (error == 0) {
  286. DEBUG_MSG_P(PSTR("[I2C] Device found at address 0x%02X\n"), address);
  287. nDevices++;
  288. }
  289. }
  290. if (nDevices == 0) DEBUG_MSG_P(PSTR("[I2C] No devices found\n"));
  291. }
  292. #if TERMINAL_SUPPORT
  293. void _i2cInitCommands() {
  294. terminalRegisterCommand(F("I2C.SCAN"), [](Embedis* e) {
  295. i2cScan();
  296. terminalOK();
  297. });
  298. terminalRegisterCommand(F("I2C.CLEAR"), [](Embedis* e) {
  299. i2cClearBus();
  300. terminalOK();
  301. });
  302. }
  303. #endif // TERMINAL_SUPPORT
  304. void i2cSetup() {
  305. const auto sda = _i2cGetSDA();
  306. const auto scl = _i2cGetSCL();
  307. #if I2C_USE_BRZO
  308. auto cst = getSetting("i2cCST", I2C_CLOCK_STRETCH_TIME);
  309. _i2c_scl_frequency = getSetting("i2cFreq", I2C_SCL_FREQUENCY);
  310. brzo_i2c_setup(sda, scl, cst);
  311. #else
  312. Wire.begin(sda, scl);
  313. #endif
  314. DEBUG_MSG_P(PSTR("[I2C] Using GPIO%02d for SDA and GPIO%02d for SCL\n"), sda, scl);
  315. #if TERMINAL_SUPPORT
  316. _i2cInitCommands();
  317. #endif
  318. #if I2C_CLEAR_BUS
  319. i2cClearBus();
  320. #endif
  321. #if I2C_PERFORM_SCAN
  322. i2cScan();
  323. #endif
  324. }
  325. #endif