Skip to content

Commit c7cbd7c

Browse files
authored
Shiftregister implementation (#135)
* Basic support of SIPO shift register * typo * add example of shiftregister for arduino and nucleo * Fix build flag for nucleof103rb * Fix wrong data pin configuration * Change README.md for Shift registers * Add API for individual register's output pin * Rewrite shift register example to show ShiftPin usage * Fix target for shiftregister example smoke test * Fix type in makefile * Add shiftregister compatble IC * Edit comment and readme
1 parent 12ac4c2 commit c7cbd7c

File tree

4 files changed

+221
-1
lines changed

4 files changed

+221
-1
lines changed

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,5 +121,7 @@ smoke-test:
121121
@md5sum ./build/test.hex
122122
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/l9110x/speed/main.go
123123
@md5sum ./build/test.hex
124+
tinygo build -size short -o ./build/test.hex -target=nucleo-f103rb ./examples/shiftregister/main.go
125+
@md5sum ./build/test.hex
124126

125127
test: clean fmt-check smoke-test

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ The following 44 devices are supported.
8787
| [PCD8544 display](http://eia.udg.edu/~forest/PCD8544_1.pdf) | SPI |
8888
| [Resistive Touchscreen (4-wire)](http://ww1.microchip.com/downloads/en/Appnotes/doc8091.pdf) | GPIO |
8989
| [Semihosting](https://wiki.segger.com/Semihosting) | Debug |
90-
| [Shift register](https://en.wikipedia.org/wiki/Shift_register#Parallel-in_serial-out_\(PISO\)) | GPIO |
90+
| [Shift register (PISO)](https://en.wikipedia.org/wiki/Shift_register#Parallel-in_serial-out_\(PISO\)) | GPIO |
91+
| [Shift registers (SIPO)](https://en.wikipedia.org/wiki/Shift_register#Serial-in_parallel-out_(SIPO)) | GPIO |
9192
| [SHT3x Digital Humidity Sensor](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/0_Datasheets/Humidity/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf) | I2C |
9293
| [SSD1306 OLED display](https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf) | I2C / SPI |
9394
| [SSD1331 TFT color display](https://www.crystalfontz.com/controllers/SolomonSystech/SSD1331/381/) | SPI |

examples/shiftregister/main.go

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package main
2+
3+
import (
4+
"machine"
5+
"time"
6+
7+
"tinygo.org/x/drivers/shiftregister"
8+
)
9+
10+
func main() {
11+
d := shiftregister.New(
12+
shiftregister.EIGHT_BITS,
13+
machine.PA6, // D12 Pin latch connected to ST_CP of 74HC595 (12)
14+
machine.PA7, // D11 Pin clock connected to SH_CP of 74HC595 (11)
15+
machine.PB6, // D10 Pin data connected to DS of 74HC595 (14)
16+
)
17+
d.Configure()
18+
19+
for {
20+
21+
// Examples using masks. This method writes all pins state at once.
22+
23+
// All pins High
24+
d.WriteMask(0xFF)
25+
delay()
26+
27+
// All pins Low
28+
d.WriteMask(0x00)
29+
delay()
30+
31+
// Some fun with masks
32+
for _, pattern := range patterns {
33+
d.WriteMask(pattern)
34+
shortDelay()
35+
}
36+
delay()
37+
d.WriteMask(0x00)
38+
39+
// Examples using individually addressable pin API. This method is slower than using mask
40+
// because all register's pins state are send for is p.Set() call.
41+
42+
// Set register's pin #4
43+
d.GetShiftPin(4).High()
44+
delay()
45+
d.GetShiftPin(4).Low()
46+
delay()
47+
48+
// Get an individual pin and use it
49+
pin := d.GetShiftPin(7)
50+
pin.High()
51+
delay()
52+
pin.Low()
53+
delay()
54+
55+
// Prepare an array of pin attached to the register
56+
pins := [8]*shiftregister.ShiftPin{}
57+
for p := 0; p < 8; p++ {
58+
pins[p] = d.GetShiftPin(p)
59+
}
60+
61+
for p := 7; p >= 0; p-- {
62+
pins[p].Low()
63+
shortDelay()
64+
pins[p].High()
65+
}
66+
67+
for p := 7; p >= 0; p-- {
68+
pins[p].High()
69+
time.Sleep(100 * time.Millisecond)
70+
pins[p].Low()
71+
}
72+
delay()
73+
}
74+
}
75+
76+
func delay() {
77+
time.Sleep(500 * time.Millisecond)
78+
}
79+
func shortDelay() {
80+
time.Sleep(100 * time.Millisecond)
81+
}
82+
83+
var patterns = []uint32{
84+
0b00000001,
85+
0b00000010,
86+
0b00000100,
87+
0b00001000,
88+
0b00010000,
89+
0b00100000,
90+
0b01000000,
91+
0b10000000,
92+
0b10000001,
93+
0b10000010,
94+
0b10000100,
95+
0b10001000,
96+
0b10010000,
97+
0b10100000,
98+
0b11000000,
99+
0b11000001,
100+
0b11000010,
101+
0b11000100,
102+
0b11001000,
103+
0b11010000,
104+
0b11100000,
105+
0b11100001,
106+
0b11100010,
107+
0b11100100,
108+
0b11101000,
109+
0b11110000,
110+
0b11110001,
111+
0b11110010,
112+
0b11110100,
113+
0b11111000,
114+
0b11111001,
115+
0b11111010,
116+
0b11111100,
117+
0b11111101,
118+
0b11111110,
119+
0b11111111,
120+
0b00000000,
121+
0b11111111,
122+
0b00000000,
123+
0b11111111,
124+
}

shiftregister/shiftregister.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Package shiftregister is for 8bit shift output register using 3 GPIO pins like SN74ALS164A, SN74AHC594, SN74AHC595, ...
2+
package shiftregister
3+
4+
import (
5+
"machine"
6+
)
7+
8+
type NumberBit int8
9+
10+
// Bit number of the register
11+
const (
12+
EIGHT_BITS NumberBit = 8
13+
SIXTEEN_BITS NumberBit = 16
14+
THIRTYTWO_BITS NumberBit = 32
15+
)
16+
17+
// Device holds pin number
18+
type Device struct {
19+
latch, clock, out machine.Pin // IC wiring
20+
bits NumberBit // Pin number
21+
mask uint32 // keep all pins state
22+
}
23+
24+
// ShiftPin is the implementation of the ShiftPin interface.
25+
// ShiftPin provide an interface like regular machine.Pin
26+
type ShiftPin struct {
27+
mask uint32 // Bit representing the pin
28+
d *Device // Reference to the register
29+
}
30+
31+
// New returns a new shift output register device
32+
func New(Bits NumberBit, Latch, Clock, Out machine.Pin) *Device {
33+
return &Device{
34+
latch: Latch,
35+
clock: Clock,
36+
out: Out,
37+
bits: Bits,
38+
}
39+
}
40+
41+
// Configure set hardware configuration
42+
func (d *Device) Configure() {
43+
d.latch.Configure(machine.PinConfig{Mode: machine.PinOutput})
44+
d.clock.Configure(machine.PinConfig{Mode: machine.PinOutput})
45+
d.out.Configure(machine.PinConfig{Mode: machine.PinOutput})
46+
d.latch.High()
47+
}
48+
49+
// WriteMask applies mask's bits to register's outputs pin
50+
// mask's MSB set Q1, LSB set Q8 (for 8 bits mask)
51+
func (d *Device) WriteMask(mask uint32) {
52+
d.mask = mask // Keep the mask for individual addressing
53+
d.latch.Low()
54+
for i := 0; i < int(d.bits); i++ {
55+
d.clock.Low()
56+
d.out.Set(mask&1 != 0)
57+
mask = mask >> 1
58+
d.clock.High()
59+
}
60+
d.latch.High()
61+
}
62+
63+
// GetShiftPin return an individually addressable pin
64+
func (d *Device) GetShiftPin(pin int) *ShiftPin {
65+
if pin < 0 || pin > int(d.bits) {
66+
panic("invalid pin number")
67+
}
68+
return &ShiftPin{
69+
mask: 1 << pin,
70+
d: d,
71+
}
72+
73+
}
74+
75+
// Set changes the value of this register pin.
76+
func (p ShiftPin) Set(value bool) {
77+
d := p.d
78+
if value {
79+
d.WriteMask(d.mask | p.mask)
80+
} else {
81+
d.WriteMask(d.mask & ^p.mask)
82+
}
83+
}
84+
85+
// High sets this shift register pin to high.
86+
func (p ShiftPin) High() {
87+
p.Set(true)
88+
}
89+
90+
// Low sets this shift register pin to low.
91+
func (p ShiftPin) Low() {
92+
p.Set(false)
93+
}

0 commit comments

Comments
 (0)