pca9685.cpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #include "pca9685.h"
  2. extern I2C i2c;
  3. DigitalOut PCA9685_PWM_nEN(PA_7);
  4. DigitalOut PCA9685_VIN_EN(PB_1);
  5. AnalogOut PCA9685_VIN(PA_5);
  6. void PCA9685_Init(void) {
  7. // Power up PCA9685 at full voltage with outputs disabled
  8. PCA9685_VIN.write(1);
  9. PCA9685_VIN_EN.write(1);
  10. PCA9685_PWM_nEN.write(1);
  11. char buffer[sizeof(REG_MODE1)+sizeof(REG_MODE2)+1] = {0};
  12. buffer[0] = FIELD_OFFSET(PCM9685_REGS, MODE1);
  13. REG_MODE1 *reg1 = (REG_MODE1*)&buffer[1];
  14. reg1->AI = 1; // Turn on autoincrement
  15. reg1->SLEEP = 1; // Start disabled
  16. reg1->ALLCALL = 1; // Enable response to all call address
  17. REG_MODE2 *reg2 = (REG_MODE2*)&buffer[1+sizeof(REG_MODE1)];
  18. reg2->OUTDRV = 1; // Configure output for totem pole drive
  19. i2c.write(PCM9685_All_Call << 1, buffer, sizeof(buffer));
  20. char pre_scale[2] = {0};
  21. pre_scale[0] = FIELD_OFFSET(PCM9685_REGS, PRE_SCALE);
  22. pre_scale[1] = 0x03; // Set PWM frequency to 1526 Hz
  23. i2c.write(PCM9685_All_Call << 1, pre_scale, sizeof(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. reg1->SLEEP = 0;
  31. i2c.write(PCM9685_All_Call << 1, buffer, sizeof(buffer));
  32. // Enable outputs after configuration has been completed
  33. PCA9685_PWM_nEN.write(0);
  34. }
  35. void PCA9685_SetVoltage(float Percent) {
  36. Percent = Percent * 0.6;
  37. PCA9685_VIN.write(Percent);
  38. }
  39. void PCA9685_SetDigit(int Tube, int Digit, int Brightness) {
  40. char buffer[sizeof(LED_CTRL)+1] = {0};
  41. buffer[0] = FIELD_OFFSET(PCM9685_REGS, LED0) +
  42. (Tube_Mapping[Tube][Digit][MAP_PIN] * sizeof(LED_CTRL));
  43. LED_CTRL *reg = (LED_CTRL*)&buffer[1];
  44. if (Brightness >= PCA9685_Max_Brightness) {
  45. reg->ON_FULL = 1;
  46. } else if (Brightness == 0) {
  47. reg->OFF_FULL = 1;
  48. } else {
  49. reg->OFF = Brightness;
  50. }
  51. i2c.write(Tube_Mapping[Tube][Digit][MAP_ADDR] << 1, buffer, sizeof(buffer));
  52. }
  53. void PCA9685_SetDot(int Brightness) {
  54. char buffer[sizeof(LED_CTRL)+1] = {0};
  55. buffer[0] = FIELD_OFFSET(PCM9685_REGS, TUBE_DOT_PIN);
  56. LED_CTRL *reg = (LED_CTRL*)&buffer[1];
  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 << 1, buffer, sizeof(buffer));
  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. }