~ruther/avr-shift-registers

ref: 67cde4955cfd8a7717372d7084c080de2b29e1b0 avr-shift-registers/src/sr/seduce.h -rw-r--r-- 12.4 KiB
67cde495 — František Boháček chore: update README 5 years ago
                                                                                
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
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
#ifndef _SHIFT_REGISTERS_SEDUCE
#define _SHIFT_REGISTERS_SEDUCE

#ifndef SR_DDR_OFFSET
    #define SR_DDR_OFFSET 1
#endif

#ifndef SR_PORT_OFFSET
    #define SR_PORT_OFFSET 2
#endif

typedef unsigned char bool;
typedef unsigned char byte;

/**
 * @brief Hold data port info.
 * 
 * Structure used to hold PIN registers
 * along with a bit position.
 * 
 * DDR and PORT registers will be automatically located
 * to save some RAM. offset of DDR can be set
 * using #define SR_DDR_OFFSET (default 1). For PORT use
 * #define SR_PORT_OFFSET (default 2). This number is then
 * added to the PIN address
 * 
 * Can be used to dynamically save a position of I/O .
 * 
 * @note Function @see data_position_create can be used as an shorthand for creating DataPosition.
 * 
 * Example usage:
 * @code
 *  data_position_create(&PINA, 1); // Pass position 1 of PINA
 * @endcode
 */
typedef struct DataPosition {
    volatile byte* pin;
    byte position;
} DataPosition;

typedef enum {
    SR_PISO,
    SR_SIPO
} ShiftRegisterTypeHeader;

typedef struct {
    const ShiftRegisterTypeHeader type;
    const DataPosition clockEnable;
    const DataPosition clockPulse;
    int waitTime;
} ShiftRegister;

typedef struct {
    const ShiftRegister shiftRegister;
    const DataPosition output;
    const DataPosition parallelLoad;
} PisoShiftRegister;

typedef struct {
    const ShiftRegister shiftRegister;
    const DataPosition input;
    const DataPosition outputEnable;
    const DataPosition pushOutput;
} SipoShiftRegister;

/**
 * @brief Create DataPosition struct.
 * 
 * Pointers to PORT and DDR are automatically calculated.
 * Check out DataPosition documentation for more information.
 * 
 * @param pin Pointer to PIN register (for example &PINA).
 * @param position Position within the register. 
 * @return DataPosition 
 * @note 0 is for LSB. 7 is for MSB. PORTA1 can be used.
 */
extern const DataPosition data_position_create(volatile byte* pin, byte position);

/**
 * @brief Get PIN value of DataPosition.
 * 
 * @param position 
 * @return true When PIN (input) is HIGH.
 * @return false When PIN (input) is LOW.
 */
extern bool data_position_get_pin(const DataPosition position);

/**
 * @brief Set PORT value of DataPosition.
 * 
 * This function makes DataPosition PORT register value 1.
 * If the port is OUTPUT, it will output 5V.
 * If the port is INPUT, the pull up resistor will be activated.
 * 
 * @param position 
 */
extern void data_position_set_port(const DataPosition position);

/**
 * @brief Reset PORT value of DataPosition.
 * 
 * This function makes DataPosition PORT register value 0.
 * If the port is OUTPUT, it will output 0V.
 * If the port is INPUT, the pull up resistor will be deactivated.
 * 
 * @param position 
 */
extern void data_position_reset_port(const DataPosition position);

/**
 * @brief Set DDR value of DataPosition
 * 
 * This function makes DataPosition DDR register value 1 and thus making it OUTPUT.
 * 
 * @param position 
 */
extern void data_position_set_ddr(const DataPosition position);

/**
 * @brief Reset DDR value of DataPosition.
 * 
 * This function makes DataPosition DDR register value 0 and thus making it INPUT.
 * 
 * @param position 
 */
extern void data_position_reset_ddr(const DataPosition position);

/*******************************************************************************
 *                                                                             *
 *                               SHIFT REGISTER                                *
 *  Part to define basic shift register functions used for both PISO and SIPO  *
 *                                                                             *
 *******************************************************************************/

/**
 * @brief Create shift register.
 * 
 * This function creates generic shift register.
 * Functions beginning with avr_piso_shift_register may be used
 * with this type of ShiftRegister.
 * 
 * @param type
 * @param clockEnable
 * @param clockPulse
 * @param waitTime
 * @return ShiftRegister 
 * 
 * @note You should always init the shift register after creating it. Use @see avr_piso_shift_register_init.
 */
extern const ShiftRegister avr_shift_register_create(
    ShiftRegisterTypeHeader type,
    const DataPosition clockEnable,
    const DataPosition clockPulse,
    int waitTime
);

/**
 * @brief Send clock pulse to shift register.
 * 
 * This function makes the clockPulse position HIGH for specified waitTime
 * Then makes it LOW again.`
 * 
 * @param shiftRegister
 */
extern void avr_shift_register_clock_pulse(const ShiftRegister shiftRegister);

/**
 * @brief Enable shift register clock.
 * 
 * This function enables the DataPosition for clockEnable.
 * The clock must be enabled before using the sift register
 * Otherwise the shift register won't do anything.
 * 
 * For SIPO registers if clockEnable is made low
 * the register is also cleared.
 * 
 * @param shiftRegister
 * @note This function will be called in the init function.
 */
extern void avr_shift_register_enable_clock(const ShiftRegister shiftRegister);

/**
 * @brief Disable shift register clock.
 * 
 * This funciton disables the DataPosition for clockEnable.
 * @see avr_shift_register_enable_clock for more info
 * 
 * @note some SIPO registers can be cleared using this function.
 * 
 * @param shiftRegister
 */
extern void avr_shift_register_disable_clock(const ShiftRegister shiftRegister);

/*******************************************************************************
 *                                                                             *
 *                                     PISO                                    *
 *  Part to define PISO shift register functions to allow shifting and getting *
 *  input from the parallel-in/serial-out shift register                       *
 *                                                                             *
 *******************************************************************************/

/**
 * @brief Create PISO shift register.
 * 
 * This function creates PISO shift register.
 * Functions beginning with avr_piso_shift_register may be used
 * with this type of ShiftRegister.
 * 
 * @param clockEnable Can be specified as CE in datasheet.
 * @param clockPulse Can be specified as CP in datasheet.
 * @param output Can be specified as Q7 in datasheet. Be careful not to use negative Q7.
 * @param parallelLoad Can be specified as PL.
 * @param waitTime Used to wait when pulsing the clock
 * @return PisoShiftRegister 
 * 
 * @note You should always init the shift register after creating it. Use @see avr_piso_shift_register_init.
 */
extern const PisoShiftRegister avr_piso_shift_register_create(
    const DataPosition clockEnable,
    const DataPosition clockPulse,
    const DataPosition output,
    const DataPosition parallelLoad,
    int waitTime
);

/**
 * @brief Setup base values for PISO shift register.
 * 
 * This function initializes the DataPositions so they are correctly set as
 * inputs or outputs.
 * 
 * @see avr_shift_register_enable_clock is also called to enable the clock.
 * 
 * @param shiftRegister
 */
extern void avr_piso_shift_register_init(const PisoShiftRegister shiftRegister);

/**
 * @brief Asynchronously load the data
 * 
 * This function is used on shift registers
 * that have the parallel load port.
 * PL port will be set LOW and then back
 * HIGH after waitTime has passed.
 * 
 * @param shiftRegister 
 */
extern void avr_piso_shift_register_parallel_load(const PisoShiftRegister shiftRegister);

/**
 * @brief Shift next bit
 * 
 * This function shifts next bit from the PISO shift register.
 * It just makes the clockPulse HIGH and then LOW.
 * 
 * @param shiftRegister 
 */
extern void avr_piso_shift_register_shift(const PisoShiftRegister shiftRegister);

/**
 * @brief Read current bit
 * 
 * This function gets the data from the output.
 * It will return 0 for LOW or 1 for HIGH
 * 
 * @note You can read the whole byte using @see avr_piso_shift_register_read_byte
 * 
 * @param shiftRegister 
 * @return true 
 * @return false 
 */
extern bool avr_piso_shift_register_read_bit(const PisoShiftRegister shiftRegister);

/**
 * @brief Read byte from the shift register
 * 
 * This function gets byte from the output.
 * The first value read goes to the LSB.
 * 
 * @note You can read one bit using @see avr_piso_shift_register_read_bit
 * 
 * @param shiftRegister 
 * @return byte 
 */
extern byte avr_piso_shift_register_read_byte(const PisoShiftRegister shiftRegister);

/*******************************************************************************
 *                                                                             *
 *                                     SIPO                                    *
 *  Part to define SIPO shift register functions to allow shifting and passing *
 *  output to the seiarl-in/parallel-out shift register                        *
 *                                                                             *
 *******************************************************************************/

/**
 * @brief Create SIPO shift register handle.
 * 
 * This function creates SIPO shift register.
 * Functions beginning with avr_sipo_shift_register may be used
 * with this type of ShiftRegister.
 * 
 * @param clockEnable Can be specified as SRCLR in datasheet.
 * @param clockPulse Can be specified as SRCLK in datasheet.
 * @param input Can be specified as SER in datasheet.
 * @param outputEnable Can be specified as OE in datasheet.
 * @param pushOutput Can be specified as RCLK in datasheet.
 * @param waitTime Used to wait when pulsing the clock
 * @return ShiftRegisterHandle 
 * 
 * @note You should always init the shift register after creating it. Use @see avr_sipo_shift_register_init.
 */
extern const SipoShiftRegister avr_sipo_shift_register_create(
    const DataPosition clockEnable, // SRCLR
    const DataPosition clockPulse, // SRCLK
    const DataPosition input, // SER
    const DataPosition outputEnable, // OE
    const DataPosition pushOutput, // RCLK
    int waitTime
);

/**
 * @brief Setup base values for PISO shift register.
 * 
 * This function initializes the DataPositions so they are correctly set as
 * inputs or outputs.
 * 
 * @see avr_shift_register_enable_clock is also called to enable the clock.
 * 
 * @param shiftRegister
 */
extern void avr_sipo_shift_register_init(const SipoShiftRegister shiftRegister);

/**
 * @brief Shifts data by one position.
 * 
 * This function shifts next bit from the PISO shift register.
 * It just makes the clockPulse HIGH and then LOW.
 * 
 * @param shiftRegister 
 */
extern void avr_sipo_shift_register_shift(const SipoShiftRegister shiftRegister);

/**
 * @brief Write one bit to the shift register.
 * 
 * This function writes one bit to the shift register.
 * Shift function is also called to save the data.
 * 
 * @note You can read the whole byte using @see avr_sipo_shift_register_write_byte
 * 
 * @param shiftRegister 
 * @param data 
 * @param position 
 */
extern void avr_sipo_shift_register_write_bit(const SipoShiftRegister shiftRegister, byte data, int position);

/**
 * @brief Write whole byte to the shift register.
 * 
 * This function writes whole byte to the shift register.
 * The first written bit will be the LSB.
 * 
 * @note You can write only one bit using @see avr_sipo_shift_register_write_bit
 * 
 * @param shiftRegister 
 * @param data 
 */
extern void avr_sipo_shift_register_write_byte(const SipoShiftRegister shiftRegister, byte data);

/**
 * @brief Enable output DataPosition
 * 
 * This function enables the output so the shift register
 * outputs the data shifted in it.
 * 
 * @param shiftRegister 
 */
extern void avr_sipo_shift_register_enable_output(const SipoShiftRegister shiftRegister);

/**
 * @brief Disable output DataPosition
 * 
 * This function disables the output so the shift register
 * doesn't output anything.
 * 
 * @param shiftRegister 
 */
extern void avr_sipo_shift_register_disable_output(const SipoShiftRegister shiftRegister);

/**
 * @brief Psuh data to output
 * 
 * This function pushes the data from the shift register
 * to the storage register. That means the data you shift
 * in will be set only after you call this function.
 * 
 * @param shiftRegister 
 */
extern void avr_sipo_shift_register_push_data_to_output(const SipoShiftRegister shiftRegister);

/**
 * @brief Disable and enable clock to reset the SR value
 * 
 * This funciton disables the clock, then waits a bit
 * and enables the clock. Doing that the register will
 * be reset.
 * 
 * @param shiftRegister 
 */
extern void avr_sipo_shift_register_reset(const SipoShiftRegister shiftRegister);

#endif