# 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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://royals6234.gitbook.io/madmachine-examples/examples/advancedio/pca9685.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
