pca9685.cpp 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #include "mbed.h"
  2. #include "main.h"
  3. #include "pca9685.h"
  4. DigitalOut PCA9685_PWM_nEN(PA_7);
  5. DigitalOut PCA9685_VIN_EN(PB_1);
  6. AnalogOut PCA9685_VIN(PA_5);
  7. void PCA9685_Init(void) {
  8. PCA9685_REGS regs = {0};
  9. // Power up PCA9685 at full voltage with outputs disabled
  10. PCA9685_VIN.write(1);
  11. PCA9685_VIN_EN.write(1);
  12. PCA9685_PWM_nEN.write(1);
  13. regs.MODE1.AI = 1; // Turn on autoincrement
  14. regs.MODE1.SLEEP = 1; // Start disabled
  15. regs.MODE1.ALLCALL = 1; // Enable response to all call address
  16. regs.MODE2.OUTDRV = 1; // Configure output for totem pole drive
  17. I2C_Write(PCA9685_All_Call, FIELD_OFFSET(PCA9685_REGS, MODE1),
  18. regs.AS_BYTE + FIELD_OFFSET(PCA9685_REGS, MODE1),
  19. FIELD_SIZE_THROUGH(PCA9685_REGS, MODE1, MODE2));
  20. regs.PRE_SCALE = 0x03; // Set PWM frequency to 1526Hz
  21. I2C_Write(PCA9685_All_Call, FIELD_OFFSET(PCA9685_REGS, PRE_SCALE),
  22. regs.AS_BYTE + FIELD_OFFSET(PCA9685_REGS, PRE_SCALE),
  23. FIELD_SIZE_THROUGH(PCA9685_REGS, PRE_SCALE, PRE_SCALE));
  24. PCA9685_SetDot(0);
  25. for (int i = 0; i < 4; i++) {
  26. for (int j = 0; j < 10; j++) {
  27. PCA9685_SetDigit(i, j, 0);
  28. }
  29. }
  30. regs.MODE1.SLEEP = 0; // Re-enable outputs
  31. I2C_Write(PCA9685_All_Call, FIELD_OFFSET(PCA9685_REGS, MODE1),
  32. regs.AS_BYTE + FIELD_OFFSET(PCA9685_REGS, MODE1),
  33. FIELD_SIZE_THROUGH(PCA9685_REGS, MODE1, MODE1));
  34. // Enable outputs after configuration has been completed
  35. PCA9685_PWM_nEN.write(0);
  36. }
  37. void PCA9685_SetVoltage(float Percent) {
  38. Percent = Percent * 0.6;
  39. PCA9685_VIN.write(Percent);
  40. }
  41. void PCA9685_SetDigit(int Tube, int Digit, int Brightness) {
  42. LED_CTRL reg = {0};
  43. if (Brightness >= PCA9685_Max_Brightness) {
  44. reg.ON_FULL = 1;
  45. } else if (Brightness == 0) {
  46. reg.OFF_FULL = 1;
  47. } else {
  48. reg.OFF = Brightness;
  49. }
  50. I2C_Write(Tube_Mapping[Tube][Digit][MAP_ADDR],
  51. FIELD_OFFSET(PCA9685_REGS, LED0) + (Tube_Mapping[Tube][Digit][MAP_PIN] * sizeof(LED_CTRL)),
  52. reg.AS_BYTE, sizeof(LED_CTRL));
  53. }
  54. void PCA9685_SetDot(int Brightness) {
  55. LED_CTRL reg = {0};
  56. if (Brightness >= PCA9685_Max_Brightness) {
  57. reg.ON_FULL = 1;
  58. } else if (Brightness == 0) {
  59. reg.OFF_FULL = 1;
  60. } else {
  61. reg.OFF = Brightness;
  62. }
  63. I2C_Write(TUBE_DOT_ADDR, FIELD_OFFSET(PCA9685_REGS, TUBE_DOT_PIN), reg.AS_BYTE, sizeof(LED_CTRL));
  64. }
  65. void PCA9685_EnableOutput(bool Enabled) {
  66. if (Enabled) {
  67. PCA9685_PWM_nEN.write(0);
  68. } else {
  69. PCA9685_PWM_nEN.write(1);
  70. }
  71. }