pca9635.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. //Source: https://github.com/rambo/pca9635
  2. #include "pca9635.h"
  3. // Constructor
  4. pca9635::pca9635() {
  5. this->device_address = 0x70; // Default to the all-call address
  6. this->autoincrement_bits = 0x80; // Autoincrement all
  7. this->available = false;
  8. for (uint8_t i = 0; i < NUM_CHANNELS; i++) {
  9. this->pwm_values[i] = 0;
  10. }
  11. for (uint8_t i = 0; i < MODE_REGISTERS; i++) {
  12. this->led_mode_regs[i] = 0;
  13. }
  14. }
  15. void pca9635::begin(byte dev_addr, boolean wire_begin, boolean init)
  16. {
  17. device_address = dev_addr;
  18. if (wire_begin) {
  19. if (!Wire.begin(21, 22, 400000UL)) {
  20. Serial.println("Error while setup i2c bus!");
  21. }
  22. this->reset();
  23. }
  24. if (init)
  25. {
  26. if (this->set_sleep(0x0)) { // Wake up oscillators
  27. this->available = true;
  28. delayMicroseconds(500); // Wait for the oscillators to stabilize
  29. this->set_led_mode(0); // Default to full PWM mode for all drivers
  30. this->set_invert_output(1); //invert output channels to use with external nfet
  31. this->set_output_not_active_state(0x00); //LEDn=0 if OE is not set
  32. this->set_group_control(1); // setup group blinking
  33. this->set_group_dimming(0x80); // set duty cycle to 50%
  34. // this->set_driver_mode(0x00); // set to open-drain
  35. } else {
  36. this->available = false;
  37. }
  38. }
  39. }
  40. void pca9635::begin(byte dev_addr, boolean wire_begin)
  41. {
  42. pca9635::begin(dev_addr, wire_begin, false);
  43. }
  44. boolean pca9635::readSingleReg(uint8_t reg, uint8_t *data) {
  45. Wire.beginTransmission(this->device_address);
  46. if (Wire.write(reg | autoincrement_bits) != 1) return false;
  47. if (Wire.endTransmission(false)) return false; //send restart
  48. if (Wire.requestFrom((uint16_t) this->device_address,1U,true) == 1U) { // read one byte, then send stop
  49. *data = Wire.read();
  50. return true;
  51. }
  52. return false;
  53. }
  54. boolean pca9635::writeSingleReg(uint8_t reg, uint8_t data) {
  55. return this->writeManyReg(reg, 1, &data);
  56. /* Wire.beginTransmission(this->device_address);
  57. if (Wire.write(reg | autoincrement_bits) != 1) return false;
  58. if (Wire.write(data) != 1) return false;
  59. if (!Wire.endTransmission(true)) { //send stop
  60. return true;
  61. }
  62. return false;
  63. */
  64. }
  65. boolean pca9635::writeManyReg(uint8_t reg, uint8_t cnt, uint8_t *data) {
  66. Wire.beginTransmission(this->device_address);
  67. if (Wire.write(reg | autoincrement_bits) != 1) return false;
  68. if (Wire.write(data, cnt) != cnt) return false;
  69. if (!Wire.endTransmission(true)) { //send stop
  70. return true;
  71. }
  72. return false;
  73. }
  74. void pca9635::exchangeValueReg(uint8_t *reg, uint8_t mask, uint8_t value) {
  75. *reg = (*reg & mask) | value;
  76. }
  77. boolean pca9635::readModifyWriteReg(uint8_t reg, uint8_t mask, uint8_t value) {
  78. uint8_t tmp;
  79. if (!this->readSingleReg(reg, &tmp)) {
  80. Serial.println("error while reading single reg");
  81. return false;
  82. }
  83. this->exchangeValueReg(&tmp, mask, value);
  84. return this->writeSingleReg(reg, tmp);
  85. }
  86. /**
  87. * Control the led channel mode, modes:
  88. * 0=fully off
  89. * 1=fully on (no PWM)
  90. * 2=individual PWM only
  91. * 3=individual and group PWM
  92. *
  93. * Remember that led numbers start from 0
  94. */
  95. boolean pca9635::set_led_mode(byte ledno, byte mode)
  96. {
  97. byte reg = 0x17;
  98. if ( ledno >= 8 && ledno < 11)
  99. {
  100. reg = 0x16;
  101. }
  102. if ( ledno >= 4 && ledno < 8)
  103. {
  104. reg = 0x15;
  105. }
  106. if (ledno < 4)
  107. {
  108. reg = 0x14;
  109. }
  110. byte value = 0;
  111. switch (mode)
  112. {
  113. case 0:
  114. value = B00000000;
  115. break;
  116. case 1:
  117. value = B01010101;
  118. break;
  119. case 2:
  120. value = B10101010;
  121. break;
  122. case 3:
  123. value = B11111111;
  124. break;
  125. }
  126. byte mask = B00000000;
  127. switch(ledno%4)
  128. {
  129. case 0:
  130. mask = (byte)~B00000011;
  131. break;
  132. case 1:
  133. mask = (byte)~B00001100;
  134. break;
  135. case 2:
  136. mask = (byte)~B00110000;
  137. break;
  138. case 3:
  139. mask = (byte)~B11000000;
  140. break;
  141. }
  142. this->exchangeValueReg(&this->led_mode_regs[ledno/4], mask, value);
  143. return this->readModifyWriteReg(reg | autoincrement_bits, mask, value);
  144. }
  145. /**
  146. * Set mode for all leds
  147. * 0=fully off
  148. * 1=fully on (no PWM)
  149. * 2=individual PWM only
  150. * 3=individual and group PWM
  151. */
  152. boolean pca9635::set_led_mode(byte mode)
  153. {
  154. byte value;
  155. switch (mode)
  156. {
  157. case 0:
  158. value = B00000000;
  159. break;
  160. case 1:
  161. value = B01010101;
  162. break;
  163. case 2:
  164. value = B10101010;
  165. break;
  166. case 3:
  167. value = B11111111;
  168. break;
  169. default:
  170. value = 0;
  171. break;
  172. }
  173. for (uint8_t i = 0; i < MODE_REGISTERS; i++) {
  174. this->led_mode_regs[i] = value;
  175. }
  176. return this->writeManyReg(0x14 | autoincrement_bits, 4, this->led_mode_regs);
  177. }
  178. /**
  179. * Set modes to given leds
  180. * leds specified in the 'leds'-array
  181. * modes specified in the 'modes'-array
  182. */
  183. boolean pca9635::set_all_led_modes(uint8_t cnt, uint8_t leds[], uint8_t modes[]) {
  184. for (uint8_t i = 0; i < cnt; i++) {
  185. uint8_t mode = modes[i];
  186. if (mode > 3) {
  187. return false;
  188. }
  189. uint8_t ledno = leds[i];
  190. if (ledno >= NUM_CHANNELS) {
  191. return false;
  192. }
  193. this->exchangeValueReg(&this->led_mode_regs[ledno/4], ~(0x3<<(2*(ledno%4))), mode<<(2*(ledno%4)));
  194. }
  195. return this->writeManyReg(0x14 | autoincrement_bits, 4, this->led_mode_regs);
  196. }
  197. /**
  198. * Enable given SUBADDRess (1-3)
  199. */
  200. boolean pca9635::enable_subaddr(byte addr)
  201. {
  202. byte value;
  203. switch (addr)
  204. {
  205. case 1:
  206. value = _BV(3); // 0x71
  207. break;
  208. case 2:
  209. value = _BV(2); // 0x72
  210. break;
  211. case 3:
  212. value = _BV(1); // 0x74
  213. break;
  214. default:
  215. value = 0;
  216. break;
  217. }
  218. byte mask = ~value;
  219. return this->readModifyWriteReg(0x0 | autoincrement_bits, mask, value);
  220. }
  221. /**
  222. * Changes the driver mode between open drain(0x0) and totem-pole (0x1, the default)
  223. */
  224. boolean pca9635::set_driver_mode(byte mode)
  225. {
  226. return this->readModifyWriteReg(0x01 | autoincrement_bits, (byte)~_BV(2), (mode & 0x01) << 2);
  227. }
  228. /**
  229. * Changes the driver mode between not inverted(0x0, the default) and inverted (0x1)
  230. */
  231. boolean pca9635::set_invert_output(byte mode)
  232. {
  233. return this->readModifyWriteReg(0x01 | autoincrement_bits, (byte)~_BV(4), (mode & 0x01) << 4);
  234. }
  235. /**
  236. * Changes the driver inactive state: LEDn = 0 (0x00), LEDn = 1 if driver_mode = 1 or LEDn = high-impedance if driver_mode = 0 (0x01, the default) or LEDn = high-impedance (0x10)
  237. */
  238. boolean pca9635::set_output_not_active_state(byte mode)
  239. {
  240. if (mode > 2) {
  241. return false;
  242. }
  243. return this->readModifyWriteReg(0x01 | autoincrement_bits, (byte)~(_BV(0) | _BV(1)), (mode & 0x03));
  244. }
  245. /**
  246. * Changes the group control mode between dimming(0x0, the default) and blinking (0x1)
  247. */
  248. boolean pca9635::set_group_control(byte mode)
  249. {
  250. return this->readModifyWriteReg(0x01 | autoincrement_bits, (byte)~_BV(5), (mode & 0x01) << 5);
  251. }
  252. /**
  253. * Changes the oscillator mode between sleep (0x1, the default) and active (0x0)
  254. */
  255. boolean pca9635::set_sleep(byte sleep)
  256. {
  257. return this->readModifyWriteReg(0x00 | autoincrement_bits, (byte)~_BV(4), (sleep & 0x01) << 4);
  258. }
  259. /**
  260. * Sets the pwm value for given led, note that it must have previously been enabled for PWM control with set_mode
  261. *
  262. * Remember that led numbers start from 0
  263. */
  264. boolean pca9635::set_led_pwm(byte ledno, byte cycle) {
  265. byte reg = 0x02 + ledno;
  266. boolean ret = this->writeManyReg(reg | autoincrement_bits, 1, &cycle);
  267. if (ret) {
  268. this->pwm_values[ledno] = cycle;
  269. }
  270. return ret;
  271. }
  272. /**
  273. * Sets the pwm values for given leds, start led and the cnt of leds to change, note that it must have previously been enabled for PWM control with set_mode
  274. * the value for each led has to be set in the array.
  275. *
  276. * Remember that led numbers start from 0
  277. */
  278. boolean pca9635::set_all_led_pwm(uint8_t start_led, uint8_t cnt, uint8_t *cycles) {
  279. if (start_led >= NUM_CHANNELS || (start_led+cnt) >= NUM_CHANNELS) {
  280. return false;
  281. }
  282. boolean ret = this->writeManyReg((start_led + 0x02) | autoincrement_bits, cnt, cycles);
  283. if (ret) {
  284. for (uint8_t i = 0; i < cnt; i++) {
  285. pwm_values[i+start_led] = *(cycles+i);
  286. }
  287. }
  288. return ret;
  289. }
  290. /**
  291. * Sets the Group pwm value, note that it must have previously been enabled for PWM control and group PWM with set_mode
  292. */
  293. boolean pca9635::set_group_dimming(uint8_t cycle) {
  294. return this->writeManyReg(0x12 | autoincrement_bits, 1, &cycle);
  295. }
  296. /**
  297. * Sets the Group blinking frequency, note that it must have previously been enabled for PWM control and group PWM with set_mode
  298. */
  299. boolean pca9635::set_group_blinking(uint8_t freq) {
  300. return this->writeManyReg(0x13 | autoincrement_bits, 1, &freq);
  301. }
  302. /**
  303. * Do the software-reset song-and-dance, this should reset all drivers on the bus
  304. */
  305. boolean pca9635::reset(uint8_t addr) {
  306. #ifdef I2C_DEVICE_DEBUG
  307. Serial.println(F("pca9635::reset() called"));
  308. #endif
  309. Wire.beginTransmission(addr);
  310. uint8_t byteArray[2] = {0xA5, 0x5A};
  311. if (Wire.write(byteArray, 2) != 2) return false;
  312. byte result = Wire.endTransmission(true);
  313. if (result > 0)
  314. {
  315. #ifdef I2C_DEVICE_DEBUG
  316. Serial.print(F("FAILED: Wire.write(0x03, 0x5a, 0xa5); returned: "));
  317. Serial.println(result, DEC);
  318. #endif
  319. return false;
  320. }
  321. delayMicroseconds(5); // Wait for the reset to complete
  322. return true;
  323. }
  324. boolean pca9635::reset() {
  325. return this->reset(0x03);
  326. }
  327. boolean pca9635::isAvailable() {
  328. return this->available;
  329. }
  330. /**
  331. * return the current configured pwm value for the selected channel
  332. */
  333. uint8_t pca9635::getPWMValue(uint8_t channel) {
  334. if (channel < NUM_CHANNELS) {
  335. return this->pwm_values[channel];
  336. } else {
  337. return 0;
  338. }
  339. }
  340. // Instance for the all-call address
  341. pca9635 PCA9635 = pca9635();