@@ -50,19 +50,25 @@ extension SwiftyGPIO {
5050
5151 // RaspberryPis ARMv6 (all 1, Zero, Zero W) PWMs, only accessible ones, divided in channels (can use only one for each channel)
5252 static let PWMRPI1 : [ Int : [ GPIOName : PWMOutput ] ] = [
53- 0 : [ . P12: RaspberryPWM ( gpioId: 12 , alt: 0 , channel: 0 , baseAddr: 0x20000000 ) , . P18: RaspberryPWM ( gpioId: 18 , alt: 5 , channel: 0 , baseAddr: 0x20000000 ) ] ,
54- 1 : [ . P13: RaspberryPWM ( gpioId: 13 , alt: 0 , channel: 1 , baseAddr: 0x20000000 ) , . P19: RaspberryPWM ( gpioId: 19 , alt: 5 , channel: 1 , baseAddr: 0x20000000 ) ]
53+ 0 : [ . P12: RaspberryPWM ( gpioId: 12 , alt: 0 , channel: 0 , phy: RaspberryPHY . phyFor ( baseAddr: 0x20000000 ) ) ,
54+ . P18: RaspberryPWM ( gpioId: 18 , alt: 5 , channel: 0 , phy: RaspberryPHY . phyFor ( baseAddr: 0x20000000 ) ) ] ,
55+ 1 : [ . P13: RaspberryPWM ( gpioId: 13 , alt: 0 , channel: 1 , phy: RaspberryPHY . phyFor ( baseAddr: 0x20000000 ) ) ,
56+ . P19: RaspberryPWM ( gpioId: 19 , alt: 5 , channel: 1 , phy: RaspberryPHY . phyFor ( baseAddr: 0x20000000 ) ) ]
5557 ]
5658
5759 // RaspberryPis ARMv7 (2-3) PWMs, only accessible ones, divided in channels (can use only one for each channel)
5860 static let PWMRPI23 : [ Int : [ GPIOName : PWMOutput ] ] = [
59- 0 : [ . P12: RaspberryPWM ( gpioId: 12 , alt: 0 , channel: 0 , baseAddr: 0x3F000000 ) , . P18: RaspberryPWM ( gpioId: 18 , alt: 5 , channel: 0 , baseAddr: 0x3F000000 ) ] ,
60- 1 : [ . P13: RaspberryPWM ( gpioId: 13 , alt: 0 , channel: 1 , baseAddr: 0x3F000000 ) , . P19: RaspberryPWM ( gpioId: 19 , alt: 5 , channel: 1 , baseAddr: 0x3F000000 ) ]
61+ 0 : [ . P12: RaspberryPWM ( gpioId: 12 , alt: 0 , channel: 0 , phy: RaspberryPHY . phyFor ( baseAddr: 0x3F000000 ) ) ,
62+ . P18: RaspberryPWM ( gpioId: 18 , alt: 5 , channel: 0 , phy: RaspberryPHY . phyFor ( baseAddr: 0x3F000000 ) ) ] ,
63+ 1 : [ . P13: RaspberryPWM ( gpioId: 13 , alt: 0 , channel: 1 , phy: RaspberryPHY . phyFor ( baseAddr: 0x3F000000 ) ) ,
64+ . P19: RaspberryPWM ( gpioId: 19 , alt: 5 , channel: 1 , phy: RaspberryPHY . phyFor ( baseAddr: 0x3F000000 ) ) ]
6165 ]
6266 // RaspberryPi 4 PWMs, only accessible ones, divided in channels (can use only one for each channel)
6367 static let PWMRPI4 : [ Int : [ GPIOName : PWMOutput ] ] = [
64- 0 : [ . P12: RaspberryPWM ( gpioId: 12 , alt: 0 , channel: 0 , baseAddr: 0xFE000000 ) , . P18: RaspberryPWM ( gpioId: 18 , alt: 5 , channel: 0 , baseAddr: 0xFE000000 ) ] ,
65- 1 : [ . P13: RaspberryPWM ( gpioId: 13 , alt: 0 , channel: 1 , baseAddr: 0xFE000000 ) , . P19: RaspberryPWM ( gpioId: 19 , alt: 5 , channel: 1 , baseAddr: 0xFE000000 ) ]
68+ 0 : [ . P12: RaspberryPWM ( gpioId: 12 , alt: 0 , channel: 0 , phy: RaspberryPHY . phyFor ( baseAddr: 0xFE000000 ) ) ,
69+ . P18: RaspberryPWM ( gpioId: 18 , alt: 5 , channel: 0 , phy: RaspberryPHY . phyFor ( baseAddr: 0xFE000000 ) ) ] ,
70+ 1 : [ . P13: RaspberryPWM ( gpioId: 13 , alt: 0 , channel: 1 , phy: RaspberryPHY . phyFor ( baseAddr: 0xFE000000 ) ) ,
71+ . P19: RaspberryPWM ( gpioId: 19 , alt: 5 , channel: 1 , phy: RaspberryPHY . phyFor ( baseAddr: 0xFE000000 ) ) ]
6672 ]
6773}
6874
@@ -79,11 +85,21 @@ public protocol PWMOutput {
7985 func cleanupPattern( )
8086}
8187
82- public class RaspberryPWM : PWMOutput {
83- let gpioId : UInt
84- let alt : UInt
85- let channel : Int
86- let pwmdma : Int
88+ final public class RaspberryPHY {
89+ private static var existingPhy : RaspberryPHY ? = nil
90+
91+ static func phyFor( baseAddr: UInt ) -> RaspberryPHY {
92+ // If the physical base has changed, throw away the existing cache.
93+ // This generally shouldn't happen, as the base address is fixed.
94+ // It is reasonable to create a new instance if there is a mismatch, though.
95+ if let phy = existingPhy, phy. BCM2708_PERI_BASE == baseAddr {
96+ return phy
97+ }
98+
99+ let phy = RaspberryPHY ( baseAddr: baseAddr)
100+ existingPhy = phy
101+ return phy
102+ }
87103
88104 let BCM2708_PERI_BASE : UInt
89105 let GPIO_BASE : UInt // GPIO Register
@@ -95,32 +111,22 @@ public class RaspberryPWM: PWMOutput {
95111 var gpioBasePointer : UnsafeMutablePointer < UInt32 > !
96112 var pwmBasePointer : UnsafeMutablePointer < UInt32 > !
97113 var clockBasePointer : UnsafeMutablePointer < UInt32 > !
98- var dmaBasePointer : UnsafeMutablePointer < UInt32 > !
99- var dmaCallbackPointer : UnsafeMutablePointer < DMACallback > ! = nil
100- var pwmRawPointer : UnsafeMutablePointer < UInt32 > ! = nil
101- var mailbox : MailBox ! = nil
114+ var dmaBasePointers : [ UnsafeMutablePointer < UInt32 > ] ! = [ ]
102115
103- var zeroPattern : Int = 0
104- var onePattern : Int = 0
105- var symbolBits : Int = 0
106- var patternFrequency : Int = 0
107- var patternDelay : Int = 0
108- var dataLength : Int = 0
109-
110- public init ( gpioId: UInt , alt: UInt , channel: Int , baseAddr: UInt , dmanum: Int = 5 ) {
111- self . gpioId = gpioId
112- self . alt = alt
113- self . channel = channel
114- self . pwmdma = dmanum
116+ public private( set) var isInitialized : Bool = false
117+ public private( set) var isReadyForPwm : Bool = false
118+
119+ public init ( baseAddr: UInt ) {
115120 BCM2708_PERI_BASE = baseAddr
116121 GPIO_BASE = BCM2708_PERI_BASE + 0x200000 // GPIO Register
117122 PWM_BASE = BCM2708_PERI_BASE + 0x20C000 // PWM Register
118123 CLOCK_BASE = BCM2708_PERI_BASE + 0x101000 // Clock Manager Register
119124 PWM_PHY_BASE = BCM2708_PHY_BASE + 0x20C000 // PWM controller physical address
120125 }
121126
122- /// Init PWM on this pin, set alternative function
123- public func initPWM( ) {
127+ func initPhy( ) {
128+ guard !isInitialized else { return }
129+
124130 var mem_fd : Int32 = 0
125131
126132 //The only mem device that support PWM is /dev/mem
@@ -130,28 +136,103 @@ public class RaspberryPWM: PWMOutput {
130136 fatalError ( " Can't open /dev/mem , use sudo! " )
131137 }
132138
133- gpioBasePointer = memmap ( from: mem_fd, at: GPIO_BASE)
134- pwmBasePointer = memmap ( from: mem_fd, at: PWM_BASE)
135- clockBasePointer = memmap ( from: mem_fd, at: CLOCK_BASE)
139+ gpioBasePointer = memmap ( from: mem_fd, at: Int ( GPIO_BASE) )
140+ pwmBasePointer = memmap ( from: mem_fd, at: Int ( PWM_BASE) )
141+ clockBasePointer = memmap ( from: mem_fd, at: Int ( CLOCK_BASE) )
136142
137143 let DMAOffsets : [ UInt ] = [ 0x00007000 , 0x00007100 , 0x00007200 , 0x00007300 ,
138- 0x00007400 , 0x00007500 , 0x00007600 , 0x00007700 ,
139- 0x00007800 , 0x00007900 , 0x00007a00 , 0x00007b00 ,
140- 0x00007c00 , 0x00007d00 , 0x00007e00 , 0x00e05000 ]
144+ 0x00007400 , 0x00007500 , 0x00007600 , 0x00007700 ,
145+ 0x00007800 , 0x00007900 , 0x00007a00 , 0x00007b00 ,
146+ 0x00007c00 , 0x00007d00 , 0x00007e00 , 0x00e05000 ]
141147
142- func dmanumToPhysicalAddress( _ dmanum: Int ) -> UInt {
143- guard dmanum < DMAOffsets . count else { return 0 }
144- return BCM2708_PERI_BASE + DMAOffsets[ dmanum]
148+ for dma_addr in DMAOffsets . map ( { BCM2708_PERI_BASE + $0 } ) {
149+ let pageOffset = Int ( dma_addr % UInt( PAGE_SIZE) )
150+ let adjusted_dma_addr = Int ( dma_addr) - pageOffset
151+ let dma_map = UnsafeMutableRawPointer ( memmap ( from: mem_fd, at: adjusted_dma_addr) )
152+
153+ let dmaBasePointer = ( dma_map + pageOffset) . assumingMemoryBound ( to: UInt32 . self)
154+ dmaBasePointers. append ( dmaBasePointer)
145155 }
146156
147- var dma_addr = dmanumToPhysicalAddress ( pwmdma) // Address of a specific DMA Channel registers set
148- let pageOffset = Int ( dma_addr % UInt( PAGE_SIZE) )
149- dma_addr -= UInt ( pageOffset)
157+ close ( mem_fd)
158+ }
150159
151- let dma_map = UnsafeMutableRawPointer ( memmap ( from : mem_fd , at : dma_addr ) )
152- dmaBasePointer = ( dma_map + pageOffset ) . assumingMemoryBound ( to : UInt32 . self )
160+ func setPwmClock ( ) {
161+ guard !isReadyForPwm else { return }
153162
154- close ( mem_fd)
163+ killClock ( )
164+
165+ let idiv = UInt32 ( 2 ) // 250Mhz base frequency
166+ // Configure the clock and divisor that will be used to generate the signal
167+ clockBasePointer. advanced ( by: 41 ) . pointee = CLKM_PASSWD | ( idiv << CLKM_DIV_DIVI) //CM CTL DIV register: Set DIVI value
168+ clockBasePointer. advanced ( by: 40 ) . pointee = CLKM_PASSWD | CLKM_CTL_ENAB | CLKM_CTL_SRC_PLLD //CM CTL register: Enable clock, MASH 0, source PLLD
169+ pwmBasePointer. pointee = 0 //PWM CTL register: Everything at 0, enable flag included, disables previous PWM
170+ usleep ( 10 )
171+
172+ isReadyForPwm = true
173+ }
174+
175+ func killClock( ) {
176+ clockBasePointer. advanced ( by: 40 ) . pointee = CLKM_PASSWD | CLKM_CTL_KILL //CM CTL register: Set KILL flag
177+ usleep ( 10 )
178+
179+ isReadyForPwm = false
180+ }
181+
182+ /// Maps a block of memory and returns the pointer
183+ internal func memmap( from mem_fd: Int32 , at offset: Int ) -> UnsafeMutablePointer < UInt32 > {
184+ let m = mmap (
185+ nil , //Any adddress in our space will do
186+ PAGE_SIZE, //Map length
187+ PROT_READ|PROT_WRITE, // Enable reading & writting to mapped memory
188+ MAP_SHARED, //Shared with other processes
189+ mem_fd, //File to map
190+ off_t ( offset) //Offset to GPIO peripheral
191+ ) !
192+
193+ if ( Int ( bitPattern: m) == - 1 ) { //MAP_FAILED not available, but its value is (void*)-1
194+ perror ( " mmap error " )
195+ abort ( )
196+ }
197+ let pointer = m. assumingMemoryBound ( to: UInt32 . self)
198+
199+ return pointer
200+ }
201+ }
202+
203+ public class RaspberryPWM : PWMOutput {
204+ let gpioId : UInt
205+ let alt : UInt
206+ let channel : Int
207+ let pwmdma : Int
208+
209+ let phy : RaspberryPHY
210+
211+ var dmaBasePointer : UnsafeMutablePointer < UInt32 > !
212+ var dmaCallbackPointer : UnsafeMutablePointer < DMACallback > ! = nil
213+ var pwmRawPointer : UnsafeMutablePointer < UInt32 > ! = nil
214+ var mailbox : MailBox ! = nil
215+
216+ var zeroPattern : Int = 0
217+ var onePattern : Int = 0
218+ var symbolBits : Int = 0
219+ var patternFrequency : Int = 0
220+ var patternDelay : Int = 0
221+ var dataLength : Int = 0
222+
223+ public init ( gpioId: UInt , alt: UInt , channel: Int , phy: RaspberryPHY , dmanum: Int = 5 ) {
224+ self . phy = phy
225+ self . gpioId = gpioId
226+ self . alt = alt
227+ self . channel = channel
228+ self . pwmdma = dmanum
229+
230+ }
231+
232+ /// Init PWM on this pin, set alternative function
233+ public func initPWM( ) {
234+ phy. initPhy ( )
235+ dmaBasePointer = phy. dmaBasePointers [ pwmdma]
155236
156237 // set PWM alternate function for this GPIO
157238 setAlt ( )
@@ -161,34 +242,36 @@ public class RaspberryPWM: PWMOutput {
161242 /// The signal starts, asynchronously(manged by a device external to the CPU), once this method is called and
162243 /// needs to be stopped manually calling `stopPWM()`.
163244 public func startPWM( period ns: Int , duty percent: Float ) {
164- // Kill the clock
165- clockBasePointer . advanced ( by : 40 ) . pointee = CLKM_PASSWD | CLKM_CTL_KILL //CM CTL register: Set KILL flag
166- usleep ( 10 )
245+ if !phy . isReadyForPwm {
246+ phy . setPwmClock ( )
247+ }
167248
168- // If the required frequency is too high, this value reduces the number of samples (scale does the opposite)
169- let highFreqSampleReduction : UInt32 = ( ns < 750 ) ? 10 : 1
249+ // @ 250Mhz, one slot in the PWM channel is 4 ns. All valid periods are multiples of that.
250+ // Pick a range that is at least as large as requested that we can represent, and round the
251+ // desired duty cycle to the nearest whole slot.
252+ //
253+ // Double precision is used here to handle very low frequencies in the range of <15Hz.
254+ // Otherwise we lose precision calculating data.
255+ let range = UInt32 ( max ( ( Double ( ns) / 4.0 ) . rounded ( . awayFromZero) , 1 ) )
170256
171- let freq = UInt32 ( ( 1_000_000_000 / UInt( ns) ) * 100 / UInt( highFreqSampleReduction) )
172- let clkSrc : ClockSource = ( BCM2708_PERI_BASE != UInt ( 0xFE000000 ) ) ? . PLLD : . PLLDPi4 //Differend Oscillator/PLLD freq for Pi4
173- let ( idiv, scale) = calculateDIVI ( base: clkSrc, desired: UInt32 ( freq) ) //Using the faster (with known freq) available clock to reduce jitter
257+ let data = min ( UInt32 ( ( Double ( percent) * Double( range) / 100.0 ) . rounded ( . toNearestOrAwayFromZero) ) , range)
174258
175- // Configure the clock and divisor that will be used to generate the signal
176- clockBasePointer. advanced ( by: 41 ) . pointee = CLKM_PASSWD | ( idiv << CLKM_DIV_DIVI) //CM CTL DIV register: Set DIVI value
177- clockBasePointer. advanced ( by: 40 ) . pointee = CLKM_PASSWD | CLKM_CTL_ENAB | CLKM_CTL_SRC_PLLD //CM CTL register: Enable clock, MASH 0, source PLLD
178- pwmBasePointer. pointee = 0 //PWM CTL register: Everything at 0, enable flag included, disables previous PWM
179- usleep ( 10 )
180259 // Configure the parameters for the M/S algorithm, S the number of total slots in RNG1 and M the number of slots with high value in DAT1
181260 let RNG = ( channel == 0 ) ? 4 : 8
182261 let DAT = ( channel == 0 ) ? 5 : 9
183- pwmBasePointer. advanced ( by: RNG) . pointee = 100 * scale / highFreqSampleReduction //RNG1 register
184- pwmBasePointer. advanced ( by: DAT) . pointee = UInt32 ( ( percent / Float ( highFreqSampleReduction ) ) * Float ( scale ) ) //DAT1 register
262+ phy . pwmBasePointer. advanced ( by: RNG) . pointee = range //RNG1 register
263+ phy . pwmBasePointer. advanced ( by: DAT) . pointee = data //DAT1 register
185264 let PWMCTL_MSEN = ( channel == 0 ) ? PWMCTL_MSEN1 : PWMCTL_MSEN2
186265 let PWMCTL_PWEN = ( channel == 0 ) ? PWMCTL_PWEN1 : PWMCTL_PWEN2
187- pwmBasePointer. pointee = PWMCTL_MSEN | PWMCTL_PWEN //PWM CTL register, channel enabled, M/S mode
266+
267+ phy. pwmBasePointer. pointee |= PWMCTL_MSEN | PWMCTL_PWEN //PWM CTL register, channel enabled, M/S mode
188268 }
189269
190270 public func stopPWM( ) {
191- pwmBasePointer. pointee = 0 //PWM CTL register, everything at 0, enable flag included
271+ let PWMCTL_MSEN = ( channel == 0 ) ? PWMCTL_MSEN1 : PWMCTL_MSEN2
272+ let PWMCTL_PWEN = ( channel == 0 ) ? PWMCTL_PWEN1 : PWMCTL_PWEN2
273+
274+ phy. pwmBasePointer. pointee &= ~ PWMCTL_MSEN & ~ PWMCTL_PWEN //PWM CTL register, clear just the channel.
192275 }
193276
194277 /// Maps a block of memory and returns the pointer
@@ -214,7 +297,7 @@ public class RaspberryPWM: PWMOutput {
214297 /// Set the alternative function for this GPIO
215298 internal func setAlt( ) {
216299 let altid = ( self . alt<= 3 ) ? UInt32 ( self . alt+ 4 ) : self . alt== 4 ? UInt32 ( 3 ) : UInt32 ( 2 )
217- let ptr = gpioBasePointer. advanced ( by: Int ( gpioId/ 10 ) ) // GPFSELn 0..5
300+ let ptr = phy . gpioBasePointer. advanced ( by: Int ( gpioId/ 10 ) ) // GPFSELn 0..5
218301 ptr. pointee &= ~ ( 7 <<( ( UInt32 ( gpioId) % 10 ) * 3 ) )
219302 ptr. pointee |= ( altid<<( ( UInt32 ( gpioId) % 10 ) * 3 ) )
220303 }
@@ -305,11 +388,12 @@ extension RaspberryPWM {
305388 public func cleanupPattern( ) {
306389 dma_wait ( )
307390 // Stop the PWM
308- pwmBasePointer. pointee = 0
391+ phy . pwmBasePointer. pointee = 0
309392 usleep ( 10 )
310393 // Stop the clock killing the clock
311- clockBasePointer. advanced ( by: 40 ) . pointee = CLKM_PASSWD | CLKM_CTL_KILL //Set KILL flag
394+ phy . clockBasePointer. advanced ( by: 40 ) . pointee = CLKM_PASSWD | CLKM_CTL_KILL //Set KILL flag
312395 usleep ( 10 )
396+ phy. killClock ( )
313397
314398 mailbox. cleanup ( )
315399 }
@@ -337,7 +421,7 @@ extension RaspberryPWM {
337421
338422 // Round up to page size multiple
339423 let mboxsize = ( size + PAGE_SIZE - 1 ) & ~ ( PAGE_SIZE - 1 )
340- mailbox = MailBox ( handle: - 1 , size: mboxsize, isRaspi2: BCM2708_PERI_BASE != 0x20000000 )
424+ mailbox = MailBox ( handle: - 1 , size: mboxsize, isRaspi2: phy . BCM2708_PERI_BASE != 0x20000000 )
341425
342426 guard let mailbox = mailbox else { fatalError ( " Could allocate mailbox. " ) }
343427
@@ -351,33 +435,33 @@ extension RaspberryPWM {
351435 }
352436
353437 // Stop the PWM
354- pwmBasePointer. pointee = 0
438+ phy . pwmBasePointer. pointee = 0
355439 usleep ( 10 )
356440 // Stop the clock killing the clock
357- clockBasePointer . advanced ( by : 40 ) . pointee = CLKM_PASSWD | CLKM_CTL_KILL //Set KILL flag
441+ phy . killClock ( )
358442 usleep ( 10 )
359443 // Check the BUSY flag, doesn't always work
360444 //while (clockBasePointer.advanced(by: 40).pointee & (1 << 7)) != 0 {}
361445
362446 // Configure clock
363- let clkSrc : ClockSource = ( BCM2708_PERI_BASE != UInt ( 0xFE000000 ) ) ? . PLLD : . PLLDPi4 //Differend Oscillator/PLLD freq for Pi4
447+ let clkSrc : ClockSource = ( phy . BCM2708_PERI_BASE != UInt ( 0xFE000000 ) ) ? . PLLD : . PLLDPi4 //Differend Oscillator/PLLD freq for Pi4
364448 let idiv = calculateUnscaledDIVI ( base: clkSrc, desired: UInt32 ( symbolBits * patternFrequency) )
365- clockBasePointer. advanced ( by: 41 ) . pointee = CLKM_PASSWD | ( idiv << CLKM_DIV_DIVI) //Set DIVI value
366- clockBasePointer. advanced ( by: 40 ) . pointee = CLKM_PASSWD | CLKM_CTL_ENAB | CLKM_CTL_SRC_PLLD //Enable clock, MASH 0, source PLLD
449+ phy . clockBasePointer. advanced ( by: 41 ) . pointee = CLKM_PASSWD | ( idiv << CLKM_DIV_DIVI) //Set DIVI value
450+ phy . clockBasePointer. advanced ( by: 40 ) . pointee = CLKM_PASSWD | CLKM_CTL_ENAB | CLKM_CTL_SRC_PLLD //Enable clock, MASH 0, source PLLD
367451 usleep ( 10 )
368452 // Check the BUSY flag, doesn't always work
369453 //while (clockBasePointer.advanced(by: 40).pointee & (1 << 7)) != 0 {}
370454
371455 // Configure PWM
372- pwmBasePointer. advanced ( by: 4 ) . pointee = 32 // RNG1: 32-bits per word to serialize
456+ phy . pwmBasePointer. advanced ( by: 4 ) . pointee = 32 // RNG1: 32-bits per word to serialize
373457 usleep ( 10 )
374- pwmBasePointer. pointee = PWMCTL_CLRF1
458+ phy . pwmBasePointer. pointee = PWMCTL_CLRF1
375459 usleep ( 10 )
376- pwmBasePointer. advanced ( by: 2 ) . pointee = PWMDMAC_ENAB | 7 << PWMDMAC_PANIC | 3 << PWMDMAC_DREQ
460+ phy . pwmBasePointer. advanced ( by: 2 ) . pointee = PWMDMAC_ENAB | 7 << PWMDMAC_PANIC | 3 << PWMDMAC_DREQ
377461 usleep ( 10 )
378- pwmBasePointer. pointee = PWMCTL_USEF1 | PWMCTL_MODE1 //| PWMCTL_USEF2 | PWMCTL_MODE2 // For 2nd chan
462+ phy . pwmBasePointer. pointee = PWMCTL_USEF1 | PWMCTL_MODE1 //| PWMCTL_USEF2 | PWMCTL_MODE2 // For 2nd chan
379463 usleep ( 10 )
380- pwmBasePointer. pointee |= PWMCTL_PWEN1 //| PWMCTL_PWEN2 // For 2nd chan
464+ phy . pwmBasePointer. pointee |= PWMCTL_PWEN1 //| PWMCTL_PWEN2 // For 2nd chan
381465
382466 // Initialize the DMA control block
383467 dmaCallbackPointer. pointee = DMACallback (
@@ -387,7 +471,7 @@ extension RaspberryPWM {
387471 UInt32 ( 0x5 << DMATI_PERMAP) | // PWM peripheral
388472 DMATI_SRC_INC, // Increment src addr
389473 source_ad: UInt32 ( mailbox. virtualTobaseBusAddress ( UnsafeMutableRawPointer ( pwmRawPointer) ) ) ,
390- dest_ad: UInt32 ( PWM_PHY_BASE + 0x18 ) , // PWM FIF1 Register, shared between channels
474+ dest_ad: UInt32 ( phy . PWM_PHY_BASE + 0x18 ) , // PWM FIF1 Register, shared between channels
391475 txfr_len: UInt32 ( dataSize) ,
392476 stride: 0 ,
393477 nextconbk: 0 )
0 commit comments