123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- #include "mbed.h"
- #include "main.h"
- #include "pca9685.h"
- DigitalOut PCA9685_PWM_nEN(PA_7);
- DigitalOut PCA9685_VIN_EN(PB_1);
- AnalogOut PCA9685_VIN(PA_5);
- void PCA9685_Init(void) {
- PCA9685_REGS regs = {0};
-
- // Power up PCA9685 at full voltage with outputs disabled
- PCA9685_VIN.write(1);
- PCA9685_VIN_EN.write(1);
- PCA9685_PWM_nEN.write(1);
- regs.MODE1.AI = 1; // Turn on autoincrement
- regs.MODE1.SLEEP = 1; // Start disabled
- regs.MODE1.ALLCALL = 1; // Enable response to all call address
-
- regs.MODE2.OUTDRV = 1; // Configure output for totem pole drive
-
- I2C_Write(PCA9685_All_Call, FIELD_OFFSET(PCA9685_REGS, MODE1),
- regs.AS_BYTE + FIELD_OFFSET(PCA9685_REGS, MODE1),
- FIELD_SIZE_THROUGH(PCA9685_REGS, MODE1, MODE2));
-
- regs.PRE_SCALE = 0x03; // Set PWM frequency to 1526Hz
- I2C_Write(PCA9685_All_Call, FIELD_OFFSET(PCA9685_REGS, PRE_SCALE),
- regs.AS_BYTE + FIELD_OFFSET(PCA9685_REGS, PRE_SCALE),
- FIELD_SIZE_THROUGH(PCA9685_REGS, PRE_SCALE, PRE_SCALE));
-
- PCA9685_SetDot(0);
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 10; j++) {
- PCA9685_SetDigit(i, j, 0);
- }
- }
-
- regs.MODE1.SLEEP = 0; // Re-enable outputs
-
- I2C_Write(PCA9685_All_Call, FIELD_OFFSET(PCA9685_REGS, MODE1),
- regs.AS_BYTE + FIELD_OFFSET(PCA9685_REGS, MODE1),
- FIELD_SIZE_THROUGH(PCA9685_REGS, MODE1, MODE1));
- // Enable outputs after configuration has been completed
- PCA9685_PWM_nEN.write(0);
- }
- void PCA9685_SetVoltage(float Percent) {
- Percent = Percent * 0.6;
- PCA9685_VIN.write(Percent);
- }
- void PCA9685_SetDigit(int Tube, int Digit, int Brightness) {
- LED_CTRL reg = {0};
- if (Brightness >= PCA9685_Max_Brightness) {
- reg.ON_FULL = 1;
- } else if (Brightness == 0) {
- reg.OFF_FULL = 1;
- } else {
- reg.OFF = Brightness;
- }
- I2C_Write(Tube_Mapping[Tube][Digit][MAP_ADDR],
- FIELD_OFFSET(PCA9685_REGS, LED0) + (Tube_Mapping[Tube][Digit][MAP_PIN] * sizeof(LED_CTRL)),
- reg.AS_BYTE, sizeof(LED_CTRL));
- }
- void PCA9685_SetDigitPwm(int Tube, int Digit, int StartPwm, int EndPwm) {
- LED_CTRL reg = {0};
- reg.ON = StartPwm;
- reg.OFF = EndPwm;
- if (EndPwm - StartPwm >= PCA9685_Max_Brightness) {
- reg.ON_FULL = 1;
- } else if (EndPwm == 0) {
- reg.OFF_FULL = 1;
- }
- I2C_Write(Tube_Mapping[Tube][Digit][MAP_ADDR],
- FIELD_OFFSET(PCA9685_REGS, LED0) + (Tube_Mapping[Tube][Digit][MAP_PIN] * sizeof(LED_CTRL)),
- reg.AS_BYTE, sizeof(LED_CTRL));
- }
- void PCA9685_SetDot(int Brightness) {
- LED_CTRL reg = {0};
- if (Brightness >= PCA9685_Max_Brightness) {
- reg.ON_FULL = 1;
- } else if (Brightness == 0) {
- reg.OFF_FULL = 1;
- } else {
- reg.OFF = Brightness;
- }
- I2C_Write(TUBE_DOT_ADDR, FIELD_OFFSET(PCA9685_REGS, TUBE_DOT_PIN), reg.AS_BYTE, sizeof(LED_CTRL));
- }
- void PCA9685_SetDotPwm(int StartPwm, int EndPwm) {
- LED_CTRL reg = {0};
- reg.ON = StartPwm;
- reg.OFF = EndPwm;
- if (EndPwm - StartPwm >= PCA9685_Max_Brightness) {
- reg.ON_FULL = 1;
- } else if (EndPwm == 0) {
- reg.OFF_FULL = 1;
- } else if (EndPwm >= PCA9685_Max_Brightness) {
- reg.OFF = 0xFFF;
- }
- I2C_Write(TUBE_DOT_ADDR, FIELD_OFFSET(PCA9685_REGS, TUBE_DOT_PIN), reg.AS_BYTE, sizeof(LED_CTRL));
- }
- void PCA9685_EnableOutput(bool Enabled) {
- if (Enabled) {
- PCA9685_PWM_nEN.write(0);
- } else {
- PCA9685_PWM_nEN.write(1);
- }
- }
|