@@ -3,31 +3,31 @@ Package rpio provides GPIO access on the Raspberry PI without any need
3
3
for external c libraries (eg. WiringPi or BCM2835).
4
4
5
5
Supports simple operations such as:
6
- - Pin mode/direction (input/output/clock/pwm,alt0,alt1,alt2,alt3,alt4,alt5)
7
- - Pin write (high/low)
8
- - Pin read (high/low)
9
- - Pin edge detection (no/rise/fall/any)
10
- - Pull up/down/off
6
+ - Pin mode/direction (input/output/clock/pwm,alt0,alt1,alt2,alt3,alt4,alt5)
7
+ - Pin write (high/low)
8
+ - Pin read (high/low)
9
+ - Pin edge detection (no/rise/fall/any)
10
+ - Pull up/down/off
11
11
Also clock/pwm related oparations:
12
- - Set Clock frequency
13
- - Set Duty cycle
12
+ - Set Clock frequency
13
+ - Set Duty cycle
14
14
And SPI oparations:
15
- - SPI transmit/recieve/exchange bytes
16
- - Chip select
17
- - Set speed
15
+ - SPI transmit/recieve/exchange bytes
16
+ - Set speed
17
+ - Chip select
18
18
19
19
Example of use:
20
20
21
- rpio.Open()
22
- defer rpio.Close()
21
+ rpio.Open()
22
+ defer rpio.Close()
23
23
24
- pin := rpio.Pin(4)
25
- pin.Output()
24
+ pin := rpio.Pin(4)
25
+ pin.Output()
26
26
27
- for {
28
- pin.Toggle()
29
- time.Sleep(time.Second)
30
- }
27
+ for {
28
+ pin.Toggle()
29
+ time.Sleep(time.Second)
30
+ }
31
31
32
32
The library use the raw BCM2835 pinouts, not the ports as they are mapped
33
33
on the output pins for the raspberry pi, and not the wiringPi convention.
@@ -100,10 +100,10 @@ const (
100
100
101
101
// BCM 2711 has a different mechanism for pull-up/pull-down/enable
102
102
const (
103
- GPPUPPDN0 = 57 // Pin pull-up/down for pins 15:0
104
- GPPUPPDN1 = 58 // Pin pull-up/down for pins 31:16
105
- GPPUPPDN2 = 59 // Pin pull-up/down for pins 47:32
106
- GPPUPPDN3 = 60 // Pin pull-up/down for pins 57:48
103
+ GPPUPPDN0 = 57 // Pin pull-up/down for pins 15:0
104
+ GPPUPPDN1 = 58 // Pin pull-up/down for pins 31:16
105
+ GPPUPPDN2 = 59 // Pin pull-up/down for pins 47:32
106
+ GPPUPPDN3 = 60 // Pin pull-up/down for pins 57:48
107
107
)
108
108
109
109
var (
@@ -146,6 +146,12 @@ const (
146
146
High
147
147
)
148
148
149
+ // Which PWM algorithm to use, Balanced or Mark/Space
150
+ const (
151
+ Balanced = true
152
+ MarkSpace = false
153
+ )
154
+
149
155
// Pull Up / Down / Off
150
156
const (
151
157
PullOff Pull = iota
@@ -222,6 +228,12 @@ func (pin Pin) DutyCycle(dutyLen, cycleLen uint32) {
222
228
SetDutyCycle (pin , dutyLen , cycleLen )
223
229
}
224
230
231
+ // DutyCycleWithPwmMode: Set duty cycle for Pwm pin while also specifying which PWM
232
+ // mode to use, Balanced or MarkSpace (see doc of SetDutyCycleWithPwmMode)
233
+ func (pin Pin ) DutyCycleWithPwmMode (dutyLen , cycleLen uint32 , mode bool ) {
234
+ SetDutyCycleWithPwmMode (pin , dutyLen , cycleLen , mode )
235
+ }
236
+
225
237
// Mode: Set pin Mode
226
238
func (pin Pin ) Mode (mode Mode ) {
227
239
PinMode (pin , mode )
@@ -259,7 +271,7 @@ func (pin Pin) PullOff() {
259
271
260
272
func (pin Pin ) ReadPull () Pull {
261
273
if ! isBCM2711 () {
262
- return PullNone // Can't read pull-up/pull-down state on other Pi boards
274
+ return PullNone // Can't read pull-up/pull-down state on other Pi boards
263
275
}
264
276
265
277
reg := GPPUPPDN0 + (uint8 (pin ) >> 4 )
@@ -272,7 +284,7 @@ func (pin Pin) ReadPull() Pull {
272
284
case 2 :
273
285
return PullDown
274
286
default :
275
- return PullNone // Invalid
287
+ return PullNone // Invalid
276
288
}
277
289
}
278
290
@@ -481,51 +493,51 @@ func EdgeDetected(pin Pin) bool {
481
493
}
482
494
483
495
func PullMode (pin Pin , pull Pull ) {
484
-
496
+
485
497
memlock .Lock ()
486
498
defer memlock .Unlock ()
487
499
488
500
if isBCM2711 () {
489
501
pullreg := GPPUPPDN0 + (pin >> 4 )
490
502
pullshift := (pin & 0xf ) << 1
491
-
492
- var p uint32
493
-
503
+
504
+ var p uint32
505
+
494
506
switch pull {
495
507
case PullOff :
496
508
p = 0
497
509
case PullUp :
498
510
p = 1
499
511
case PullDown :
500
- p = 2 ;
512
+ p = 2
501
513
}
502
-
514
+
503
515
// This is verbatim C code from raspi-gpio.c
504
516
pullbits := gpioMem [pullreg ]
505
517
pullbits &= ^ (3 << pullshift )
506
518
pullbits |= (p << pullshift )
507
- gpioMem [pullreg ]= pullbits
519
+ gpioMem [pullreg ] = pullbits
508
520
} else {
509
521
// Pull up/down/off register has offset 38 / 39, pull is 37
510
522
pullClkReg := pin / 32 + 38
511
523
pullReg := 37
512
524
shift := pin % 32
513
-
525
+
514
526
switch pull {
515
527
case PullDown , PullUp :
516
528
gpioMem [pullReg ] |= uint32 (pull )
517
529
case PullOff :
518
530
gpioMem [pullReg ] &^= 3
519
531
}
520
-
532
+
521
533
// Wait for value to clock in, this is ugly, sorry :(
522
534
time .Sleep (time .Microsecond )
523
-
535
+
524
536
gpioMem [pullClkReg ] = 1 << shift
525
-
537
+
526
538
// Wait for value to clock in
527
539
time .Sleep (time .Microsecond )
528
-
540
+
529
541
gpioMem [pullReg ] &^= 3
530
542
gpioMem [pullClkReg ] = 0
531
543
}
@@ -550,7 +562,7 @@ func SetFreq(pin Pin, freq int) {
550
562
if isBCM2711 () {
551
563
sourceFreq = 52000000
552
564
}
553
- const divMask = 4095 // divi and divf have 12 bits each
565
+ const divMask = 4095 // divi and divf have 12 bits each
554
566
555
567
divi := uint32 (sourceFreq / freq )
556
568
divf := uint32 (((sourceFreq % freq ) << 12 ) / freq )
@@ -627,12 +639,26 @@ func SetFreq(pin Pin, freq int) {
627
639
// The channels are:
628
640
// channel 1 (pwm0) for pins 12, 18, 40
629
641
// channel 2 (pwm1) for pins 13, 19, 41, 45.
642
+ //
643
+ // NOTE without root permission this function will simply do nothing successfully
630
644
func SetDutyCycle (pin Pin , dutyLen , cycleLen uint32 ) {
645
+ SetDutyCycleWithPwmMode (pin , dutyLen , cycleLen , MarkSpace )
646
+
647
+ }
648
+
649
+ // SetDutyCycleWithPwmMode extends SetDutyCycle to allow for the specification of the PWM
650
+ // algorithm to be used, Balanced or Mark/Space. The constants Balanced or MarkSpace
651
+ // as the value. See 'SetDutyCycle(pin, dutyLen, cycleLen)' above for more information
652
+ // regarding how to use 'SetDutyCycleWithPwmMode()'.
653
+ //
654
+ // NOTE without root permission this function will simply do nothing successfully
655
+ func SetDutyCycleWithPwmMode (pin Pin , dutyLen , cycleLen uint32 , mode bool ) {
631
656
const pwmCtlReg = 0
632
657
var (
633
658
pwmDatReg uint
634
659
pwmRngReg uint
635
660
shift uint // offset inside ctlReg
661
+
636
662
)
637
663
638
664
switch pin {
@@ -646,20 +672,29 @@ func SetDutyCycle(pin Pin, dutyLen, cycleLen uint32) {
646
672
shift = 8
647
673
default :
648
674
return
675
+
649
676
}
650
677
651
678
const ctlMask = 255 // ctl setting has 8 bits for each channel
652
679
const pwen = 1 << 0 // enable pwm
653
- const msen = 1 << 7 // use M/S transition instead of pwm algorithm
680
+ var msen uint32 = 0
681
+ // The MSEN1 field in the CTL register is at offset 7. This block starts with the assumption
682
+ // that 'msen' will be associated with channel 'pwm0'. If this is not the case, 'msen' will
683
+ // be further shifted in the next code block below to the MSEN2 field at offset 15.
684
+ if mode == MarkSpace {
685
+ msen = 1 << 7
686
+ }
654
687
655
- // reset settings
688
+ // Shifting 'pwen' and 'msen' puts the associated values at the correct offset within the CTL
689
+ // register ('pwmCtlReg'). In addition, 'msen' is associated with a PWM channel depending on the
690
+ // value of 'pin' (see above). 'msen' will either stay at offset 7, as set above for channel 'pwm0',
691
+ // or be shifted 8 bits if the the associated 'pin' is on channel 'pwm1'.
656
692
pwmMem [pwmCtlReg ] = pwmMem [pwmCtlReg ]&^(ctlMask << shift ) | msen << shift | pwen << shift
693
+
657
694
// set duty cycle
658
695
pwmMem [pwmDatReg ] = dutyLen
659
696
pwmMem [pwmRngReg ] = cycleLen
660
697
time .Sleep (time .Microsecond * 10 )
661
-
662
- // NOTE without root permission this changes will simply do nothing successfully
663
698
}
664
699
665
700
// StopPwm: Stop pwm for both channels
0 commit comments