pca9685.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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. Brightness /= 3;
  57. if (Brightness >= PCA9685_Max_Brightness) {
  58. reg.ON_FULL = 1;
  59. } else if (Brightness == 0) {
  60. reg.OFF_FULL = 1;
  61. } else {
  62. reg.OFF = Brightness;
  63. }
  64. I2C_Write(TUBE_DOT_ADDR, FIELD_OFFSET(PCA9685_REGS, TUBE_DOT_PIN), reg.AS_BYTE, sizeof(LED_CTRL));
  65. }
  66. void PCA9685_EnableOutput(bool Enabled) {
  67. if (Enabled) {
  68. PCA9685_PWM_nEN.write(0);
  69. } else {
  70. PCA9685_PWM_nEN.write(1);
  71. }
  72. }