959
|
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 "FastIO.h"
|
|
33
|
|
34
|
|
35 fio_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
|
|
52 fio_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
|
|
65 fio_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
|
|
76 void 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
|
|
95 int 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
|
|
108 void 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
|
|
159 void 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
|
|
176 void fio_shiftOut1_init(uint8_t pin)
|
|
177 {
|
|
178 fio_shiftOut1_init(fio_pinToOutputRegister(pin,HIGH),fio_pinToBit(pin));
|
|
179 }
|
|
180
|
|
181 void 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
|
|
190 void 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
|
|
264 void fio_shiftOut1(uint8_t pin, uint8_t value, boolean noLatch)
|
|
265 {
|
|
266 fio_shiftOut1(fio_pinToOutputRegister(pin, SKIP),fio_pinToBit(pin),value, noLatch);
|
|
267 }
|