Skip to content

Instantly share code, notes, and snippets.

@keybuk
Last active June 11, 2018 19:32
Show Gist options
  • Save keybuk/e61d0354580e67f4ce310400b101578a to your computer and use it in GitHub Desktop.
Save keybuk/e61d0354580e67f4ce310400b101578a to your computer and use it in GitHub Desktop.
import Foundation
import RaspberryPi
// Shutdown PWM1, clear FIFO
let pwm = try! PWM()
pwm[1].isEnabled = false
pwm.clearFifo()
// Stop the PWM clock
let clock = try! Clock()
clock[.pwm].isEnabled = false
while clock[.pwm].isRunning {}
// Grab DMA 4
let dma = try! DMA()
dma[4].isActive = false
dma[4].reset()
// Set GPIO12 to output from PWM1
let gpio = try! GPIO()
gpio[12].function = .alternateFunction0
// Set PWM1 to use DMA + FIFO in 16-bit Serializer mode
pwm.isDMAEnabled = true
pwm[1].useFifo = true
pwm[1].mode = .serializer
pwm[1].range = 16
// Set the PWM clock to 0.1ms ticks
clock[.pwm].source = .oscillator
clock[.pwm].mash = 0
clock[.pwm].divisor = ClockDivisor(integer: 1_920, fractional: 0)
// Allocate a data area for control blocks and data
let memory = try! UncachedMemory(minimumSize: MemoryLayout<DMAControlBlock>.stride + MemoryLayout<UInt32>.stride * 256)
let controlBlocks = memory.pointer.bindMemory(to: DMAControlBlock.self, capacity: 1)
let words = memory.pointer.advanced(by: MemoryLayout<DMAControlBlock>.stride).bindMemory(to: UInt32.self, capacity: 256)
// Fill the memory with the binary of 0...255, shift left because PWM uses the MSB of the data.
// (We output 8-bits of number, and an 8-bit gap of 0 because the serializer range is 16-bits)
for i in 0..<256 {
words[i] = UInt32(i) << 24
}
controlBlocks[0].peripheral = .pwm
controlBlocks[0].waitForWriteResponse = true
controlBlocks[0].sourceAddress = memory.busAddress + UInt32(MemoryLayout<DMAControlBlock>.stride)
controlBlocks[0].incrementSourceAddress = true
controlBlocks[0].destinationAddress = PWM.busAddress + 0x18 /* MemoryLayout.offset(of: \PWM.Registers.fifoInput) */
controlBlocks[0].destinationWaitsForDataRequest = true
controlBlocks[0].transferLength = UInt32(MemoryLayout<UInt32>.stride) * 256
controlBlocks[0].nextControlBlockAddress = memory.busAddress
// Enable the PWM
pwm[1].isEnabled = true
// Start the Clock
clock[.pwm].isEnabled = true
while !clock[.pwm].isRunning {}
// Enable the DMA
dma[4].controlBlockAddress = memory.busAddress
dma[4].isActive = true
debugPrint(gpio[12])
debugPrint(pwm[1])
debugPrint(clock[.pwm])
debugPrint(dma[4])
print("Running, press ENTER to stop")
let _ = readLine()
// Shutdown
dma[4].isActive = false
pwm[1].isEnabled = false
clock[.pwm].isEnabled = false
while clock[.pwm].isRunning {}
try! memory.deallocate()
print("Bye!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment