# PCA9685

## What you need

## Circuit

## Tips

## Code

### main.swift

```swift
import SwiftIO

extension PCA9685 {
    func setServoPulse(_ channel: Int, _ pulse: Int) {
        if pulse < 500 || pulse > 2500 {
            return
        }

        let value: UInt32 = UInt32(pulse) * 4096 / 2_0000
        setPWM(UInt8(channel), 0, UInt16(value))
    } 
}

let i2c = I2C(Id.I2C0)
let pwm = PCA9685(i2c)

while true {
    for pulse in stride(from: 500, through: 2500, by: 10)  {
        for channel in 0..<16 {
            pwm.setServoPulse(channel, pulse)
        }
        sleep(ms: 20)
    }
}
```

### PCA9685.swift

```swift
import SwiftIO

final class PCA9685 {
    private struct Mode1: OptionSet {
        let rawValue: UInt8

        static let ALLCALL = Mode1(rawValue: 0x01)
        static let SUB3    = Mode1(rawValue: 0x02)
        static let SUB2    = Mode1(rawValue: 0x04)
        static let SUB1    = Mode1(rawValue: 0x08)
        static let SLEEP   = Mode1(rawValue: 0x10)
        static let AI      = Mode1(rawValue: 0x20)
        static let EXTCLK  = Mode1(rawValue: 0x40)
        static let RESTART = Mode1(rawValue: 0x80)

        static let all     = Mode1(rawValue: 0xFF)
    }

    private struct Mode2: OptionSet {
        let rawValue: UInt8

        static let OUTNE0 = Mode2(rawValue: 0x01)
        static let OUTNE1 = Mode2(rawValue: 0x02)
        static let OUTDRV = Mode2(rawValue: 0x04)
        static let OCH    = Mode2(rawValue: 0x08)
        static let INVRT  = Mode2(rawValue: 0x10)

        static let all    = Mode2(rawValue: 0xFF)
    }

    private enum Register: UInt8 {
        case MODE1 = 0x00
        case MODE2 = 0x01
        case SUBADR1 = 0x02
        case SUBADR2 = 0x03
        case SUBADR3 = 0x04
        case ALLCALLADR = 0x05
        case LED0_ON_L = 0x06
        case LED0_ON_H = 0x07
        case LED0_OFF_L = 0x08
        case LED0_OFF_H = 0x09
        case ALLLED_ON_L = 0xFA
        case ALLLED_ON_H = 0xFB
        case ALLLED_OFF_L = 0xFC
        case ALLLED_OFF_H = 0xFD
        case PRESCALE = 0xFE
        case TESTMODE = 0xFF
    }

    let i2c: I2C
    let address = UInt8(0x40)
    let oscFrequency = Int(25_000_000)
    let prescaleMin = Float(3)
    let prescaleMax = Float(255)

    init(_ i2c: I2C) {
        self.i2c = i2c

        reset()
        setPWMFreq(1000)
    }

    func reset() {
        writeMode1(.RESTART)
        sleep(ms: 10)
    }

    func standby() {
        let oldMode = Mode1(rawValue: readRegister(.MODE1))
        let setting = oldMode.union(.SLEEP)               //[oldMode, .SLEEP]
        writeMode1(setting)
        sleep(ms: 5)
    }

    func wakeup() {
        let oldMode = Mode1(rawValue: readRegister(.MODE1))
        var setting: Mode1 = .all
        setting.subtract(.SLEEP)
        setting.formIntersection(oldMode)

        writeMode1(setting)
    }

    func setPWMFreq(_ freq: Float) {
        var freq = freq

        if freq < 1 {
            freq = 1.0
        } else if freq > 3500 {
            freq = 3500.0
        }

        var prescaleval = (Float(oscFrequency) / (freq * 4096.0)) + 0.5 - 1
        if prescaleval < prescaleMin {
            prescaleval = prescaleMin
        } else if prescaleval > prescaleMax {
            prescaleval = prescaleMax
        }

        let prescale = UInt8(prescaleval)

        let oldMode = Mode1(rawValue: readRegister(.MODE1))
        var newMode: Mode1 = .all
        newMode.subtract(.RESTART)
        newMode.formIntersection(oldMode)
        newMode.formUnion(.SLEEP)

        writeMode1(newMode)
        writeRegister(.PRESCALE, prescale)
        writeMode1(oldMode)
        sleep(ms: 5)

        newMode = oldMode.union([.RESTART, .AI])
        writeMode1(newMode)
    }

    func setOutputMode(_ totempole: Bool) {
        let oldMode = Mode2(rawValue: readRegister(.MODE2))
        var newMode: Mode2

        if totempole {
            newMode = oldMode.union(.OUTDRV) 
        } else {
            newMode = .all
            newMode.subtract(.OUTDRV)
            newMode.formIntersection(oldMode)
        }

        writeMode2(newMode)
    }

    func readPrescale() -> UInt8 {
        return readRegister(.PRESCALE)
    }

    func getPWM(_ channel: UInt8) -> UInt8 {
        let data: [UInt8] = [Register.LED0_ON_L.rawValue + 4 * channel, 4]
        i2c.write(data, to: address)
        return i2c.readByte(from: address)
    }

    func setPWM(_ channel: UInt8, _ on: UInt16, _ off: UInt16) {
        let data: [UInt8] = [Register.LED0_ON_L.rawValue + 4 * channel,
                             UInt8(on & 0xFF),
                             UInt8(on >> 8),
                             UInt8(off & 0xFF),
                             UInt8(off >> 8)]
        i2c.write(data, to: address)
    }

    func setPin(_ channel: UInt8, _ val: UInt16, _ invert: Bool) {
        var val = val
        val = min(val, 4095)

        if invert {
            if val == 0 {
                setPWM(channel, 4096, 0)
            } else if val == 4095 {
                setPWM(channel, 0, 4096)
            } else {
                setPWM(channel, 0, 4095 - val)
            }
        } else {
            if val == 4095 {
                setPWM(channel, 4096, 0)
            } else if val == 0 {
                setPWM(channel, 0, 4096)
            } else {
                setPWM(channel, 0, val)
            }
        }
    }

    func writeMicroseconds(_ channel: UInt8, _ microseconds: UInt16) {
        var pulse = Double(microseconds)
        var pulseLength = Double(1_000_000.0)

        var prescale = Double(readPrescale())

        prescale += 1
        pulseLength *= prescale
        pulseLength /= Double(oscFrequency)

        pulse /= pulseLength
        setPWM(channel, 0, UInt16(pulse))
    }


    @inline(__always)
    private func readRegister(_ r: Register) -> UInt8 {
        i2c.write(r.rawValue, to: address)
        return i2c.readByte(from: address)
    }

    @inline(__always)
    private func writeRegister(_ r: Register, _ setting: UInt8) {
        let data: [UInt8] = [r.rawValue, setting]
        i2c.write(data, to: address)
    } 


    private func writeMode1(_ setting: Mode1) {
        let data: [UInt8] = [Register.MODE1.rawValue, setting.rawValue]
        i2c.write(data, to: address)
    }

    private func writeMode2(_ setting: Mode2) {
        let data: [UInt8] = [Register.MODE2.rawValue, setting.rawValue]
        i2c.write(data, to: address)
    }
}
```

## Video

## See Also

## References

Last revision 2020/09/10 by Johnson
