1// ---------------------------------------------------------------------------
2// Created by Florian Fida on 20/01/12
3// Copyright 2012 - Under creative commons license 3.0:
4// Attribution-ShareAlike CC BY-SA
5// http://creativecommons.org/licenses/by-sa/3.0/
6//
7// This software is furnished "as is", without technical support, and with no
8// warranty, express or implied, as to its usefulness for any purpose.
9// ---------------------------------------------------------------------------
10// fio_shiftOut1 functions are based on Shif1 protocol developed by Roman Black
11// (http://www.romanblack.com/shift1.htm)
12//
13// Thread Safe: No
14// Extendable: Yes
15//
16// @file FastIO.h
17// This file implements basic fast IO routines.
18//
19// @brief
20//
21// @version API 1.0.0
22//
23// @author Florian Fida -
24//
25// 2012-03-16 bperrybap updated fio_shiftout() to be smaller & faster
26//
27// @todo:
28// support chipkit:
29// (https://github.com/chipKIT32/chipKIT32-MAX/blob/master/hardware/pic32/
30// cores/pic32/wiring_digital.c)
31// ---------------------------------------------------------------------------
32#include "Visuino_FastIO.h"
33
34
35fio_register fio_pinToOutputRegister(uint8_t pin, uint8_t initial_state)
36{
37 pinMode(pin, OUTPUT);
38
39 if(initial_state != SKIP)
40 {
41 digitalWrite(pin, initial_state); // also turns off pwm timer
42 }
43#ifdef FIO_FALLBACK
44 // just wasting memory if not using fast io...
45 return 0;
46#else
47 return portOutputRegister(digitalPinToPort(pin));
48#endif
49}
50
51
52fio_register fio_pinToInputRegister(uint8_t pin)
53{
54 pinMode(pin, INPUT);
55 digitalWrite(pin, LOW); // also turns off pwm timer and pullup
56#ifdef FIO_FALLBACK
57 // just wasting memory if not using fast io...
58 return 0;
59#else
60 return portInputRegister(digitalPinToPort(pin));
61#endif
62}
63
64
65fio_bit fio_pinToBit(uint8_t pin)
66{
67#ifdef FIO_FALLBACK
68 // (ab)use the bit variable to store the pin
69 return pin;
70#else
71 return digitalPinToBitMask(pin);
72#endif
73}
74
75
76void fio_digitalWrite(fio_register pinRegister, fio_bit pinBit, uint8_t value)
77{
78#ifdef FIO_FALLBACK
79 digitalWrite(pinBit, value);
80#else
81 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
82 {
83 if(value == LOW)
84 {
85 fio_digitalWrite_LOW(pinRegister,pinBit);
86 }
87 else
88 {
89 fio_digitalWrite_HIGH(pinRegister,pinBit);
90 }
91 }
92#endif
93}
94
95int fio_digitalRead(fio_register pinRegister, uint8_t pinBit)
96{
97#ifdef FIO_FALLBACK
98 return digitalRead (pinBit);
99#else
100 if (*pinRegister & pinBit)
101 {
102 return HIGH;
103 }
104 return LOW;
105#endif
106}
107
108void fio_shiftOut (fio_register dataRegister, fio_bit dataBit,
109 fio_register clockRegister, fio_bit clockBit,
110 uint8_t value, uint8_t bitOrder)
111{
112 // # disable interrupts
113 int8_t i;
114
115 if(bitOrder == LSBFIRST)
116 {
117 for(i = 0; i < 8; i++)
118 {
119 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
120 {
121 if(value & 1)
122 {
123 fio_digitalWrite_HIGH(dataRegister, dataBit);
124 }
125 else
126 {
127 fio_digitalWrite_LOW(dataRegister, dataBit);
128 }
129 value >>= 1;
130 fio_digitalWrite_HIGH (clockRegister, clockBit);
131 fio_digitalWrite_LOW (clockRegister,clockBit);
132 }
133 }
134
135 }
136 else
137 {
138 for(i = 0; i < 8; i++)
139 {
140 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
141 {
142 if(value & 0x80)
143 {
144 fio_digitalWrite_HIGH(dataRegister, dataBit);
145 }
146 else
147 {
148 fio_digitalWrite_LOW(dataRegister, dataBit);
149 }
150 value <<= 1;
151 fio_digitalWrite_HIGH (clockRegister, clockBit);
152 fio_digitalWrite_LOW (clockRegister,clockBit);
153 }
154 }
155 }
156}
157
158
159void fio_shiftOut(fio_register dataRegister, fio_bit dataBit,
160 fio_register clockRegister, fio_bit clockBit)
161{
162 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
163 {
164 // shift out 0x0 (B00000000) fast, byte order is irrelevant
165 fio_digitalWrite_LOW (dataRegister, dataBit);
166
167 for(uint8_t i = 0; i<8; ++i)
168 {
169 fio_digitalWrite_HIGH (clockRegister, clockBit);
170 fio_digitalWrite_SWITCH (clockRegister, clockBit);
171 }
172 }
173}
174
175
176void fio_shiftOut1_init(uint8_t pin)
177{
178 fio_shiftOut1_init(fio_pinToOutputRegister(pin,HIGH),fio_pinToBit(pin));
179}
180
181void fio_shiftOut1_init(fio_register shift1Register, fio_bit shift1Bit)
182{
183 // Make sure that capacitors are charged
184 // 300us is an educated guess...
185 fio_digitalWrite(shift1Register,shift1Bit,HIGH);
186 delayMicroseconds(300);
187}
188
189
190void fio_shiftOut1(fio_register shift1Register, fio_bit shift1Bit, uint8_t value,
191 boolean noLatch)
192{
193 /*
194 * this function are based on Shif1 protocol developed by Roman Black
195 * (http://www.romanblack.com/shift1.htm)
196 *
197 * test sketches:
198 * http://pastebin.com/raw.php?i=2hnC9v2Z
199 * http://pastebin.com/raw.php?i=bGg4DhXQ
200 * http://pastebin.com/raw.php?i=tg1ZFiM5
201 * http://pastebin.com/raw.php?i=93ExPDD3 - cascading
202 * tested with:
203 * TPIC6595N - seems to work fine (circuit: http://www.3guys1laser.com/
204 * arduino-one-wire-shift-register-prototype)
205 * 7HC595N
206 */
207
208 // iterate but ignore last bit (is it correct now?)
209 for(int8_t i = 7; i>=0; --i)
210 {
211
212 // assume that pin is HIGH (smokin' pot all day... :) - requires
213 // initialization
214 if(value & _BV(i))
215 {
216 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
217 {
218 // HIGH = 1 Bit
219 fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW);
220 //hold pin LOW for 1us - done! :)
221 fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,HIGH);
222 } // end critical section
223 //hold pin HIGH for 15us
224 delayMicroseconds(15);
225 }
226 else
227 {
228 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
229 {
230 // LOW = 0 Bit
231 fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW);
232 // hold pin LOW for 15us
233 delayMicroseconds(15);
234 fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,HIGH);
235 } // end critical section
236
237 // hold pin HIGH for 30us
238 delayMicroseconds(30);
239 }
240 if(!noLatch && i==1)
241 {
242 break;
243 }
244 }
245
246 if(!noLatch)
247 {
248 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
249 {
250 // send last bit (=LOW) and Latch command
251 fio_digitalWrite_SWITCHTO(shift1Register,shift1Bit,LOW);
252 } // end critical section
253 delayMicroseconds(199); // Hold pin low for 200us
254
255 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
256 {
257 fio_digitalWrite_HIGH(shift1Register,shift1Bit);
258 } // end critical section
259 delayMicroseconds(299); // Hold pin high for 300us and leave it that
260 // way - using explicit HIGH here, just in case.
261 }
262}
263
264void fio_shiftOut1(uint8_t pin, uint8_t value, boolean noLatch)
265{
266 fio_shiftOut1(fio_pinToOutputRegister(pin, SKIP),fio_pinToBit(pin),value, noLatch);
267}