-
Notifications
You must be signed in to change notification settings - Fork 90
/
FastIO.h
242 lines (216 loc) · 8.29 KB
/
FastIO.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
// ---------------------------------------------------------------------------
// Created by Florian Fida on 20/01/12
// Copyright (C) - 2018
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License v3.0
// along with this program.
// If not, see <https://www.gnu.org/licenses/gpl-3.0.en.html>.
//
// ---------------------------------------------------------------------------
//
// fio_shiftOut1 functions are based on Shif1 protocol developed by Roman Black
// (http://www.romanblack.com/shift1.htm)
//
// Thread Safe: No
// Extendable: Yes
//
// @file FastIO.h
// This file implements basic fast IO routines.
//
// @brief
//
// @version API 1.0.0
//
// @author Florian Fida -
// 2012-03-16 bperrybap mods for chipkit32 (pic32) Arduino
// support chipkit:
// (https://github.com/chipKIT32/chipKIT32-MAX/blob/master/hardware/pic32/
// cores/pic32/wiring_digital.c)
// ---------------------------------------------------------------------------
#ifndef _FAST_IO_H_
#define _FAST_IO_H_
#if (ARDUINO < 100)
#include <WProgram.h>
#else
#include <Arduino.h>
#endif
#include <pins_arduino.h> // pleasing sanguino core
#include <inttypes.h>
#define SKIP 0x23
#if defined (__AVR__)
#include <util/atomic.h> // for critical section management
typedef uint8_t fio_bit;
typedef volatile uint8_t *fio_register;
// __AVR__ processor end
#elif defined(__PIC32MX__)
typedef uint32_t fio_bit;
typedef volatile uint32_t *fio_register;
// __PIC32MX__ processor end
#else
// fallback to Arduino standard digital i/o routines
#define FIO_FALLBACK
#define ATOMIC_BLOCK(dummy) if(true)
#define ATOMIC_RESTORESTATE
typedef uint8_t fio_bit;
typedef uint8_t fio_register;
#endif // Processor dependent fast IO definition
#if !defined(FIO_FALLBACK) && !defined(ATOMIC_BLOCK)
/*
* Define an ATOMIC_BLOCK that implements ATOMIC_FORCEON type
* Using the portable Arduino interrupts() and noInterrupts()
*/
#define ATOMIC_RESTORESTATE ATOMIC_FORCEON // sorry, no support for save/restore yet.
#define ATOMIC_FORCEON uint8_t sreg_save \
__attribute__((__cleanup__(__iSeiParam))) = 0
static __inline__ uint8_t __iCliRetVal(void)
{
noInterrupts();
return(1);
}
static __inline__ void __iSeiParam(const uint8_t *__s)
{
interrupts();
}
#define ATOMIC_BLOCK(type) for(type, __Todo = __iCliRetVal(); __Todo; __Todo = 0)
#endif // end of block to create compatible ATOMIC_BLOCK()
/*!
@defined
@abstract Performs a bitwise shift.
@discussion Defines _BV bit shift which is very dependent macro defined by
Atmel.
\note The bit shift is performed by the compiler which then inserts the
result into the code. Thus, there is no run-time overhead when using
_BV().
*/
#ifndef _BV
#define _BV(bit) (1 << (bit))
#endif
/*!
@function
@abstract Get the output register for specified pin.
@discussion if fast digital IO is disabled this function returns NULL
@param pin[in] Number of a digital pin
@result Register
*/
fio_register fio_pinToOutputRegister(uint8_t pin, uint8_t initial_state = LOW);
/*!
@function
@abstract Get the input register for specified pin.
@discussion if fast digital IO is disabled this function returns NULL
@param pin[in] Number of a digital pin
@result Register
*/
fio_register fio_pinToInputRegister(uint8_t pin);
/*!
@function
@abstract Find the bit which belongs to specified pin
@discussion if fast digitalWrite is disabled this function returns the pin
@param pin[in] Number of a digital pin
@result Bit
*/
fio_bit fio_pinToBit(uint8_t pin);
/*!
@method
@abstract direct digital write
@discussion without any checks
@discussion falls back to normal digitalWrite if fast io is disabled
@param pinRegister[in] Register - ignored if fast digital write is disabled
@param pinBit[in] Bit - Pin if fast digital write is disabled
@param value[in] desired output
*/
// __attribute__ ((always_inline)) /* let the optimizer decide that for now */
void fio_digitalWrite ( fio_register pinRegister, fio_bit pinBit, uint8_t value );
/**
* This is where the magic happens that makes things fast.
* Implemented as preprocessor directives to force inlining
* SWITCH is fast for FIO but probably slow for FIO_FALLBACK so SWITCHTO is recommended if the value is known.
*/
#ifndef FIO_FALLBACK
#define fio_digitalWrite_LOW(reg,bit) *reg &= ~bit
#define fio_digitalWrite_HIGH(reg,bit) *reg |= bit
#define fio_digitalWrite_SWITCH(reg,bit) *reg ^= bit
#define fio_digitalWrite_SWITCHTO(reg,bit,val) fio_digitalWrite_SWITCH(reg,bit)
#else
// reg -> dummy NULL, bit -> pin
#define fio_digitalWrite_HIGH(reg,bit) digitalWrite(bit,HIGH)
#define fio_digitalWrite_LOW(reg,bit) digitalWrite(bit,LOW)
#define fio_digitalWrite_SWITCH(reg,bit) digitalWrite(bit, !digitalRead(bit))
#define fio_digitalWrite_SWITCHTO(reg,bit,val) digitalWrite(bit,val);
#endif
/*!
@function
@abstract direct digital read
@discussion without any checks
@discussion falls back to normal digitalRead if fast io is disabled
@param pinRegister[in] Register - ignored if fast io is disabled
@param pinBit[in] Bit - Pin if fast io is disabled
@result Value read from pin
*/
int fio_digitalRead ( fio_register pinRegister, fio_bit pinBit );
/*!
@method
@abstract faster shift out
@discussion using fast digital write
@discussion falls back to normal digitalWrite if fastio is disabled
@param dataRegister[in] Register of data pin - ignored if fast digital write is disabled
@param dataBit[in] Bit of data pin - Pin if fast digital write is disabled
@param clockRegister[in] Register of data pin - ignored if fast digital write is disabled
@param clockBit[in] Bit of data pin - Pin if fast digital write is disabled
@param bitOrder[in] bit order
*/
void fio_shiftOut( fio_register dataRegister, fio_bit dataBit, fio_register clockRegister,
fio_bit clockBit, uint8_t value, uint8_t bitOrder );
/*!
@method
@abstract faster shift out clear
@discussion using fast digital write
@discussion falls back to normal digitalWrite if fastio is disabled
@param dataRegister[in] Register of data pin - ignored if fast digital write is disabled
@param dataBit[in] Bit of data pin - Pin if fast digital write is disabled
@param clockRegister[in] Register of data pin - ignored if fast digital write is disabled
@param clockBit[in] Bit of data pin - Pin if fast digital write is disabled
*/
void fio_shiftOut(fio_register dataRegister, fio_bit dataBit, fio_register clockRegister, fio_bit clockBit);
/*!
* @method
* @abstract one wire shift out
* @discussion protocol needs initialisation (fio_shiftOut1_init)
* @param shift1Register[in] pins register
* @param shift1Bit[in] pins bit
* @param value[in] value to shift out, last byte is ignored and always shifted out LOW
*/
void fio_shiftOut1(fio_register shift1Register, fio_bit shift1Bit, uint8_t value, boolean noLatch = false);
/*!
* @method
* @abstract one wire shift out
* @discussion protocol needs initialisation (fio_shiftOut1_init)
* @param pin[in] digital pin
* @param value[in] value to shift out, last byte is ignored and always shifted out LOW
*/
void fio_shiftOut1(uint8_t pin, uint8_t value, boolean noLatch = false);
/*!
* @method
* @abstract initializes one wire shift out protocol
* @discussion Puts pin to HIGH state and delays until Capacitors are charged.
* @param shift1Register[in] pins register
* @param shift1Bit[in] pins bit
*/
void fio_shiftOut1_init(fio_register shift1Register, fio_bit shift1Bit);
/*!
* @method
* @abstract initializes one wire shift out protocol
* @discussion Puts pin to HIGH state and delays until Capacitors are charged.
* @param pin[in] digital pin
*/
void fio_shiftOut1_init(uint8_t pin);
#endif // FAST_IO_H