11//
22// FILE: FastShiftOut.cpp
33// AUTHOR: Rob Tillaart
4- // VERSION: 0.4.0
4+ // VERSION: 0.4.1
55// PURPOSE: ShiftOut that implements the Print interface
66// DATE: 2013-08-22
77// URL: https://github.com/RobTillaart/FastShiftOut
@@ -170,8 +170,12 @@ size_t FastShiftOut::writeLSBFIRST(uint8_t data)
170170 uint8_t oldSREG = SREG;
171171 noInterrupts ();
172172
173- if ((value & 0x01 ) == 0 ) *localDataOutRegister &= outmask2;
174- else *localDataOutRegister |= outmask1;
173+ // See discussion #17
174+ uint8_t d0 = *localDataOutRegister & outmask2; // cache 0
175+ uint8_t d1 = d0 | outmask1; // cache 1
176+
177+ if ((value & 0x01 ) == 0 ) *localDataOutRegister = d0;
178+ else *localDataOutRegister = d1;
175179 // *_clockRegister |= cbmask1;
176180 // *_clockRegister &= cbmask2;
177181 // following code is allowed as interrupts are disabled.
@@ -180,44 +184,44 @@ size_t FastShiftOut::writeLSBFIRST(uint8_t data)
180184 *localClockRegister = r | cbmask1; // set one bit
181185 *localClockRegister = r; // reset bit
182186
183- if ((value & 0x02 ) == 0 ) *localDataOutRegister &= outmask2 ;
184- else *localDataOutRegister |= outmask1 ;
187+ if ((value & 0x02 ) == 0 ) *localDataOutRegister = d0 ;
188+ else *localDataOutRegister = d1 ;
185189 r = *localClockRegister;
186190 *localClockRegister = r | cbmask1; // set one bit
187191 *localClockRegister = r; // reset it
188192
189- if ((value & 0x04 ) == 0 ) *localDataOutRegister &= outmask2 ;
190- else *localDataOutRegister |= outmask1 ;
193+ if ((value & 0x04 ) == 0 ) *localDataOutRegister = d0 ;
194+ else *localDataOutRegister = d1 ;
191195 r = *localClockRegister;
192196 *localClockRegister = r | cbmask1; // set one bit
193197 *localClockRegister = r; // reset it
194198
195- if ((value & 0x08 ) == 0 ) *localDataOutRegister &= outmask2 ;
196- else *localDataOutRegister |= outmask1 ;
199+ if ((value & 0x08 ) == 0 ) *localDataOutRegister = d0 ;
200+ else *localDataOutRegister = d1 ;
197201 r = *localClockRegister;
198202 *localClockRegister = r | cbmask1; // set one bit
199203 *localClockRegister = r; // reset it
200204
201- if ((value & 0x10 ) == 0 ) *localDataOutRegister &= outmask2 ;
202- else *localDataOutRegister |= outmask1 ;
205+ if ((value & 0x10 ) == 0 ) *localDataOutRegister = d0 ;
206+ else *localDataOutRegister = d1 ;
203207 r = *localClockRegister;
204208 *localClockRegister = r | cbmask1; // set one bit
205209 *localClockRegister = r; // reset it
206210
207- if ((value & 0x20 ) == 0 ) *localDataOutRegister &= outmask2 ;
208- else *localDataOutRegister |= outmask1 ;
211+ if ((value & 0x20 ) == 0 ) *localDataOutRegister = d0 ;
212+ else *localDataOutRegister = d1 ;
209213 r = *localClockRegister;
210214 *localClockRegister = r | cbmask1; // set one bit
211215 *localClockRegister = r; // reset it
212216
213- if ((value & 0x40 ) == 0 ) *localDataOutRegister &= outmask2 ;
214- else *localDataOutRegister |= outmask1 ;
217+ if ((value & 0x40 ) == 0 ) *localDataOutRegister = d0 ;
218+ else *localDataOutRegister = d1 ;
215219 r = *localClockRegister;
216220 *localClockRegister = r | cbmask1; // set one bit
217221 *localClockRegister = r; // reset it
218222
219- if ((value & 0x80 ) == 0 ) *localDataOutRegister &= outmask2 ;
220- else *localDataOutRegister |= outmask1 ;
223+ if ((value & 0x80 ) == 0 ) *localDataOutRegister = d0 ;
224+ else *localDataOutRegister = d1 ;
221225 r = *localClockRegister;
222226 *localClockRegister = r | cbmask1; // set one bit
223227 *localClockRegister = r; // reset it
@@ -238,11 +242,14 @@ size_t FastShiftOut::writeLSBFIRST(uint8_t data)
238242 uint8_t oldSREG = SREG;
239243 noInterrupts ();
240244
245+ // See discussion #17
246+ uint8_t d0 = *localDataOutRegister & outmask2; // cache 0
247+ uint8_t d1 = d0 | outmask1; // cache 1
241248 for (uint8_t m = 1 ; m > 0 ; m <<= 1 )
242249 {
243250 // process one bit
244- if ((value & m) == 0 ) *localDataOutRegister &= outmask2 ;
245- else *localDataOutRegister |= outmask1 ;
251+ if ((value & m) == 0 ) *localDataOutRegister = d0 ;
252+ else *localDataOutRegister = d1 ;
246253 uint8_t r = *localClockRegister;
247254 *localClockRegister = r | cbmask1; // set one bit
248255 *localClockRegister = r; // reset it
@@ -284,8 +291,12 @@ size_t FastShiftOut::writeMSBFIRST(uint8_t data)
284291 uint8_t oldSREG = SREG;
285292 noInterrupts ();
286293
287- if ((value & 0x80 ) == 0 ) *localDataOutRegister &= outmask2;
288- else *localDataOutRegister |= outmask1;
294+ // See discussion #17
295+ uint8_t d0 = *localDataOutRegister & outmask2; // cache 0
296+ uint8_t d1 = d0 | outmask1; // cache 1
297+
298+ if ((value & 0x80 ) == 0 ) *localDataOutRegister = d0;
299+ else *localDataOutRegister = d1;
289300 // *localClockRegister |= cbmask1;
290301 // *localClockRegister &= cbmask2;
291302 // following code is allowed as interrupts are disabled.
@@ -294,44 +305,44 @@ size_t FastShiftOut::writeMSBFIRST(uint8_t data)
294305 *localClockRegister = r | cbmask1; // set one bit
295306 *localClockRegister = r; // reset it
296307
297- if ((value & 0x40 ) == 0 ) *localDataOutRegister &= outmask2 ;
298- else *localDataOutRegister |= outmask1 ;
308+ if ((value & 0x40 ) == 0 ) *localDataOutRegister = d0 ;
309+ else *localDataOutRegister = d1 ;
299310 r = *localClockRegister;
300311 *localClockRegister = r | cbmask1; // set one bit
301312 *localClockRegister = r; // reset it
302313
303- if ((value & 0x20 ) == 0 ) *localDataOutRegister &= outmask2 ;
304- else *localDataOutRegister |= outmask1 ;
314+ if ((value & 0x20 ) == 0 ) *localDataOutRegister = d0 ;
315+ else *localDataOutRegister = d1 ;
305316 r = *localClockRegister;
306317 *localClockRegister = r | cbmask1; // set one bit
307318 *localClockRegister = r; // reset it
308319
309- if ((value & 0x10 ) == 0 ) *localDataOutRegister &= outmask2 ;
310- else *localDataOutRegister |= outmask1 ;
320+ if ((value & 0x10 ) == 0 ) *localDataOutRegister = d0 ;
321+ else *localDataOutRegister = d1 ;
311322 r = *localClockRegister;
312323 *localClockRegister = r | cbmask1; // set one bit
313324 *localClockRegister = r; // reset it
314325
315- if ((value & 0x08 ) == 0 ) *localDataOutRegister &= outmask2 ;
316- else *localDataOutRegister |= outmask1 ;
326+ if ((value & 0x08 ) == 0 ) *localDataOutRegister = d0 ;
327+ else *localDataOutRegister = d1 ;
317328 r = *localClockRegister;
318329 *localClockRegister = r | cbmask1; // set one bit
319330 *localClockRegister = r; // reset it
320331
321- if ((value & 0x04 ) == 0 ) *localDataOutRegister &= outmask2 ;
322- else *localDataOutRegister |= outmask1 ;
332+ if ((value & 0x04 ) == 0 ) *localDataOutRegister = d0 ;
333+ else *localDataOutRegister = d1 ;
323334 r = *localClockRegister;
324335 *localClockRegister = r | cbmask1; // set one bit
325336 *localClockRegister = r; // reset it
326337
327- if ((value & 0x02 ) == 0 ) *localDataOutRegister &= outmask2 ;
328- else *localDataOutRegister |= outmask1 ;
338+ if ((value & 0x02 ) == 0 ) *localDataOutRegister = d0 ;
339+ else *localDataOutRegister = d1 ;
329340 r = *localClockRegister;
330341 *localClockRegister = r | cbmask1; // set one bit
331342 *localClockRegister = r; // reset it
332343
333- if ((value & 0x01 ) == 0 ) *localDataOutRegister &= outmask2 ;
334- else *localDataOutRegister |= outmask1 ;
344+ if ((value & 0x01 ) == 0 ) *localDataOutRegister = d0 ;
345+ else *localDataOutRegister = d1 ;
335346 r = *localClockRegister;
336347 *localClockRegister = r | cbmask1; // set one bit
337348 *localClockRegister = r; // reset it
@@ -352,16 +363,20 @@ size_t FastShiftOut::writeMSBFIRST(uint8_t data)
352363 uint8_t oldSREG = SREG;
353364 noInterrupts ();
354365
366+ // See discussion #17
367+ uint8_t d0 = *localDataOutRegister & outmask2; // cache 0
368+ uint8_t d1 = d0 | outmask1; // cache 1
355369 for (uint8_t m = 0x80 ; m > 0 ; m >>= 1 )
356370 {
357371 // process one bit
358- if ((value & m) == 0 ) *localDataOutRegister &= outmask2 ;
359- else *localDataOutRegister |= outmask1 ;
372+ if ((value & m) == 0 ) *localDataOutRegister = d0 ;
373+ else *localDataOutRegister = d1 ;
360374 uint8_t r = *localClockRegister;
361375 *localClockRegister = r | cbmask1; // set one bit
362376 *localClockRegister = r; // reset it
363377 }
364378
379+
365380 // restore interrupt state
366381 SREG = oldSREG;
367382
0 commit comments