1
1
//
2
2
// FILE: FastShiftOut.cpp
3
3
// AUTHOR: Rob Tillaart
4
- // VERSION: 0.4.0
4
+ // VERSION: 0.4.1
5
5
// PURPOSE: ShiftOut that implements the Print interface
6
6
// DATE: 2013-08-22
7
7
// URL: https://github.com/RobTillaart/FastShiftOut
@@ -170,8 +170,12 @@ size_t FastShiftOut::writeLSBFIRST(uint8_t data)
170
170
uint8_t oldSREG = SREG;
171
171
noInterrupts ();
172
172
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;
175
179
// *_clockRegister |= cbmask1;
176
180
// *_clockRegister &= cbmask2;
177
181
// following code is allowed as interrupts are disabled.
@@ -180,44 +184,44 @@ size_t FastShiftOut::writeLSBFIRST(uint8_t data)
180
184
*localClockRegister = r | cbmask1; // set one bit
181
185
*localClockRegister = r; // reset bit
182
186
183
- if ((value & 0x02 ) == 0 ) *localDataOutRegister &= outmask2 ;
184
- else *localDataOutRegister |= outmask1 ;
187
+ if ((value & 0x02 ) == 0 ) *localDataOutRegister = d0 ;
188
+ else *localDataOutRegister = d1 ;
185
189
r = *localClockRegister;
186
190
*localClockRegister = r | cbmask1; // set one bit
187
191
*localClockRegister = r; // reset it
188
192
189
- if ((value & 0x04 ) == 0 ) *localDataOutRegister &= outmask2 ;
190
- else *localDataOutRegister |= outmask1 ;
193
+ if ((value & 0x04 ) == 0 ) *localDataOutRegister = d0 ;
194
+ else *localDataOutRegister = d1 ;
191
195
r = *localClockRegister;
192
196
*localClockRegister = r | cbmask1; // set one bit
193
197
*localClockRegister = r; // reset it
194
198
195
- if ((value & 0x08 ) == 0 ) *localDataOutRegister &= outmask2 ;
196
- else *localDataOutRegister |= outmask1 ;
199
+ if ((value & 0x08 ) == 0 ) *localDataOutRegister = d0 ;
200
+ else *localDataOutRegister = d1 ;
197
201
r = *localClockRegister;
198
202
*localClockRegister = r | cbmask1; // set one bit
199
203
*localClockRegister = r; // reset it
200
204
201
- if ((value & 0x10 ) == 0 ) *localDataOutRegister &= outmask2 ;
202
- else *localDataOutRegister |= outmask1 ;
205
+ if ((value & 0x10 ) == 0 ) *localDataOutRegister = d0 ;
206
+ else *localDataOutRegister = d1 ;
203
207
r = *localClockRegister;
204
208
*localClockRegister = r | cbmask1; // set one bit
205
209
*localClockRegister = r; // reset it
206
210
207
- if ((value & 0x20 ) == 0 ) *localDataOutRegister &= outmask2 ;
208
- else *localDataOutRegister |= outmask1 ;
211
+ if ((value & 0x20 ) == 0 ) *localDataOutRegister = d0 ;
212
+ else *localDataOutRegister = d1 ;
209
213
r = *localClockRegister;
210
214
*localClockRegister = r | cbmask1; // set one bit
211
215
*localClockRegister = r; // reset it
212
216
213
- if ((value & 0x40 ) == 0 ) *localDataOutRegister &= outmask2 ;
214
- else *localDataOutRegister |= outmask1 ;
217
+ if ((value & 0x40 ) == 0 ) *localDataOutRegister = d0 ;
218
+ else *localDataOutRegister = d1 ;
215
219
r = *localClockRegister;
216
220
*localClockRegister = r | cbmask1; // set one bit
217
221
*localClockRegister = r; // reset it
218
222
219
- if ((value & 0x80 ) == 0 ) *localDataOutRegister &= outmask2 ;
220
- else *localDataOutRegister |= outmask1 ;
223
+ if ((value & 0x80 ) == 0 ) *localDataOutRegister = d0 ;
224
+ else *localDataOutRegister = d1 ;
221
225
r = *localClockRegister;
222
226
*localClockRegister = r | cbmask1; // set one bit
223
227
*localClockRegister = r; // reset it
@@ -238,11 +242,14 @@ size_t FastShiftOut::writeLSBFIRST(uint8_t data)
238
242
uint8_t oldSREG = SREG;
239
243
noInterrupts ();
240
244
245
+ // See discussion #17
246
+ uint8_t d0 = *localDataOutRegister & outmask2; // cache 0
247
+ uint8_t d1 = d0 | outmask1; // cache 1
241
248
for (uint8_t m = 1 ; m > 0 ; m <<= 1 )
242
249
{
243
250
// 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 ;
246
253
uint8_t r = *localClockRegister;
247
254
*localClockRegister = r | cbmask1; // set one bit
248
255
*localClockRegister = r; // reset it
@@ -284,8 +291,12 @@ size_t FastShiftOut::writeMSBFIRST(uint8_t data)
284
291
uint8_t oldSREG = SREG;
285
292
noInterrupts ();
286
293
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;
289
300
// *localClockRegister |= cbmask1;
290
301
// *localClockRegister &= cbmask2;
291
302
// following code is allowed as interrupts are disabled.
@@ -294,44 +305,44 @@ size_t FastShiftOut::writeMSBFIRST(uint8_t data)
294
305
*localClockRegister = r | cbmask1; // set one bit
295
306
*localClockRegister = r; // reset it
296
307
297
- if ((value & 0x40 ) == 0 ) *localDataOutRegister &= outmask2 ;
298
- else *localDataOutRegister |= outmask1 ;
308
+ if ((value & 0x40 ) == 0 ) *localDataOutRegister = d0 ;
309
+ else *localDataOutRegister = d1 ;
299
310
r = *localClockRegister;
300
311
*localClockRegister = r | cbmask1; // set one bit
301
312
*localClockRegister = r; // reset it
302
313
303
- if ((value & 0x20 ) == 0 ) *localDataOutRegister &= outmask2 ;
304
- else *localDataOutRegister |= outmask1 ;
314
+ if ((value & 0x20 ) == 0 ) *localDataOutRegister = d0 ;
315
+ else *localDataOutRegister = d1 ;
305
316
r = *localClockRegister;
306
317
*localClockRegister = r | cbmask1; // set one bit
307
318
*localClockRegister = r; // reset it
308
319
309
- if ((value & 0x10 ) == 0 ) *localDataOutRegister &= outmask2 ;
310
- else *localDataOutRegister |= outmask1 ;
320
+ if ((value & 0x10 ) == 0 ) *localDataOutRegister = d0 ;
321
+ else *localDataOutRegister = d1 ;
311
322
r = *localClockRegister;
312
323
*localClockRegister = r | cbmask1; // set one bit
313
324
*localClockRegister = r; // reset it
314
325
315
- if ((value & 0x08 ) == 0 ) *localDataOutRegister &= outmask2 ;
316
- else *localDataOutRegister |= outmask1 ;
326
+ if ((value & 0x08 ) == 0 ) *localDataOutRegister = d0 ;
327
+ else *localDataOutRegister = d1 ;
317
328
r = *localClockRegister;
318
329
*localClockRegister = r | cbmask1; // set one bit
319
330
*localClockRegister = r; // reset it
320
331
321
- if ((value & 0x04 ) == 0 ) *localDataOutRegister &= outmask2 ;
322
- else *localDataOutRegister |= outmask1 ;
332
+ if ((value & 0x04 ) == 0 ) *localDataOutRegister = d0 ;
333
+ else *localDataOutRegister = d1 ;
323
334
r = *localClockRegister;
324
335
*localClockRegister = r | cbmask1; // set one bit
325
336
*localClockRegister = r; // reset it
326
337
327
- if ((value & 0x02 ) == 0 ) *localDataOutRegister &= outmask2 ;
328
- else *localDataOutRegister |= outmask1 ;
338
+ if ((value & 0x02 ) == 0 ) *localDataOutRegister = d0 ;
339
+ else *localDataOutRegister = d1 ;
329
340
r = *localClockRegister;
330
341
*localClockRegister = r | cbmask1; // set one bit
331
342
*localClockRegister = r; // reset it
332
343
333
- if ((value & 0x01 ) == 0 ) *localDataOutRegister &= outmask2 ;
334
- else *localDataOutRegister |= outmask1 ;
344
+ if ((value & 0x01 ) == 0 ) *localDataOutRegister = d0 ;
345
+ else *localDataOutRegister = d1 ;
335
346
r = *localClockRegister;
336
347
*localClockRegister = r | cbmask1; // set one bit
337
348
*localClockRegister = r; // reset it
@@ -352,16 +363,20 @@ size_t FastShiftOut::writeMSBFIRST(uint8_t data)
352
363
uint8_t oldSREG = SREG;
353
364
noInterrupts ();
354
365
366
+ // See discussion #17
367
+ uint8_t d0 = *localDataOutRegister & outmask2; // cache 0
368
+ uint8_t d1 = d0 | outmask1; // cache 1
355
369
for (uint8_t m = 0x80 ; m > 0 ; m >>= 1 )
356
370
{
357
371
// 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 ;
360
374
uint8_t r = *localClockRegister;
361
375
*localClockRegister = r | cbmask1; // set one bit
362
376
*localClockRegister = r; // reset it
363
377
}
364
378
379
+
365
380
// restore interrupt state
366
381
SREG = oldSREG;
367
382
0 commit comments