Accessing Shift Registers¶
- Date:
2017-08-18
Intro¶
Driving LEDs or 7-Segment Registers can be done in several ways. This document explains, how to interface them with shift registers. A shift register will receive 8 bit of data on a connection with 2 signals: data and clock. After the complete byte has been transfered, a third signal, latch, can be used to assert the newly received byte on the corresponding 8 output pins. A shift register is, in a way, a serial to parallel converter. Interestingly, shift registers can be chained.
For example, one can transfer 4 Bytes through a chain of 4 shift register chips. After the transfer asserting the latch signal will make the transfered bytes appear on all the output pins simultaneously.
I strongly prefer shift registers and thus continuous signals on LEDs over the multiplexing (and thus flickering) methods.
Code Details¶
We need to define 3 pins corresponding to the acutal hardware layout:
\ abakus display
PORTD 2 portpin: sr_latch
PORTD 3 portpin: sr_clock
PORTD 4 portpin: sr_data
Then +sr will set the pins up correctly (never assume that pins
are setup in a specific way before you start using them):
: +sr
sr_latch pin_output sr_latch high
sr_clock pin_output sr_clock low
sr_data pin_output sr_data high
;
bit>sr will clock out just one bit and nothing else:
: bit>sr ( bit -- )
if sr_data high else sr_data low then
sr_clock high sr_clock low
;
The shift registers I use expect the most significant bit first. This
could be otherwise. So byte>sr clock out one byte. The loop can be
written differently, of course.
: get.bit ( byte pos -- bit )
1 swap lshift \ -- byte bitmask
and \ -- bit
;
\ clock one byte out, MSB first!
: byte>sr ( byte -- )
0 7 do
dup i get.bit \ 7 6 5 ... 0: MSB first!
bit>sr
-1 +loop
drop
;
So far data is transfered, but not asserted onto the output pins.
So >sr adds asserting a low pulse on pin latch:
: >sr
byte>sr
sr_latch low sr_latch high
;
Putting it all together¶
The main program will know, how many shift registers are chained (if
any), thus a function like n>sr will be needed: clock out a known
number of bytes, then assert the latch signal.
: n>sr ( c1 .. cn n -- )
0 ?do
byte>sr
loop
sr_latch low sr_latch high
;
The Code¶
1\ 2017-05-10 shiftregister.fs
2\
3\ Written in 2017 by Erich Wälde <erich.waelde@forth-ev.de>
4\
5\ To the extent possible under law, the author(s) have dedicated
6\ all copyright and related and neighboring rights to this software
7\ to the public domain worldwide. This software is distributed
8\ without any warranty.
9\
10\ You should have received a copy of the CC0 Public Domain
11\ Dedication along with this software. If not, see
12\ <http://creativecommons.org/publicdomain/zero/1.0/>.
13\
14\
15\ needs pin definitions
16\ PORTD 2 portpin: sr_latch
17\ PORTD 3 portpin: sr_clock
18\ PORTD 4 portpin: sr_data
19\ words:
20\ +sr ( -- ) \ enable shift register
21\ emit.sr ( n -- ) \ transfer 1 Byte
22\ type.sr ( xn-1 .. x0 n -- ) \ n Bytes
23
24: +sr
25 sr_latch pin_output sr_latch high
26 sr_clock pin_output sr_clock low
27 sr_data pin_output sr_data high
28;
29
30: bit>sr ( bit -- )
31 if sr_data high else sr_data low then
32 sr_clock high sr_clock low
33;
34
35: get.bit ( byte pos -- bit )
36 1 swap lshift \ -- byte bitmask
37 and \ -- bit
38;
39
40\ clock one byte out, MSB first!
41: byte>sr ( byte -- )
42 0 7 do
43 dup i get.bit
44 bit>sr
45 -1 +loop
46 drop
47;