~ruther/avr-shift-registers

ref: 1f2a92a06212f4f39cef70035f3250a2ae43e640 avr-shift-registers/src/sr/seduce.h -rw-r--r-- 12.6 KiB
1f2a92a0 — František Boháček fix: code 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
#ifndef _SHIFT_REGISTERS_SEDUCE
#define _SHIFT_REGISTERS_SEDUCE

// TODO: make this working with flash memory so the data is not placed on RAM
// TODO: assume PINB is x. then DDRB is x + 1 and PORTB is x + 2.

/**
 * @file seduce.h
 * @author Rutherther
 * @date 9 Sep 2020
 * @brief File containing public exports of the library.
 * 
 * This header should be included in projects that use this library.
 * There aren't any other headers that should be imported.
 * Other headers suffixed using _internal should be used only
 * internally from within the library.
 * 
 * @see DataPosition
 * @see ShiftRegisterHandle
 */

/**
 * @brief Handle to work with the shift registers.
 * 
 * This handle can be obtained using @see avr_piso_shift_register_init for PISO
 * or @see avr_sipo_shift_register_init for SIPO.
 * PISO stands for parallel-in/serial-out (used for getting input from shift register).
 * SIPO stands for serial-in/parallel-out (used for passing output using shift register).
 * 
 */
typedef void* ShiftRegisterHandle;
typedef unsigned char bool;
typedef unsigned char byte;

/**
 * @brief Hold data port info.
 * 
 * Structure used to hold DDR, PORT and PIN registers
 * along with a bit position.
 * 
 * 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(&DDRA, &PORTA, &PINA, 1); // Pass position 1 of PINA
 * @endcode
 */
typedef struct DataPosition {
    volatile byte* ddr;
    volatile byte* port;
    volatile byte* pin;
    byte position;
} DataPosition;

/**
 * @brief Create DataPosition struct.
 * 
 * @param ddr Pointer to DDR register (for example &DDRA).
 * @param port Pointer to PORT register (for example &PORTA).
 * @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 DataPosition* data_position_create(volatile byte* ddr, volatile byte* port, volatile byte* pin, byte position);

/**
 * @brief Destroy DataPosition
 * 
 * @param position 
 */
extern void data_position_destroy(const DataPosition* 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 Send clock pulse to shift register.
 * 
 * This function makes the clockPulse position HIGH for specified waitTime
 * Then makes it LOW again.`
 * 
 * @param shiftRegisterHandle 
 */
extern void avr_shift_register_clock_pulse(ShiftRegisterHandle shiftRegisterHandle);

/**
 * @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 shiftRegisterHandle 
 * @note This function will be called in the init function.
 */
extern void avr_shift_register_enable_clock(ShiftRegisterHandle shiftRegisterHandle);

/**
 * @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 shiftRegisterHandle 
 */
extern void avr_shift_register_disable_clock(ShiftRegisterHandle shiftRegisterHandle);

/*******************************************************************************
 *                                                                             *
 *                                     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 ShiftRegisterHandle 
 * 
 * @note You should always init the shift register after creating it. Use @see avr_piso_shift_register_init.
 */
extern ShiftRegisterHandle 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 shiftRegisterHandle
 */
extern void avr_piso_shift_register_init(ShiftRegisterHandle shiftRegisterHandle);

/**
 * @brief Destroy and free PISO shift register memory
 * 
 * @param shiftRegisterHandle 
 */
extern void avr_piso_shift_register_destroy(ShiftRegisterHandle shiftRegisterHandle);

/**
 * @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 shiftRegisterHandle 
 */
extern void avr_piso_shift_register_parallel_load(ShiftRegisterHandle shiftRegisterHandle);

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

/**
 * @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 shiftRegisterHandle 
 * @return true 
 * @return false 
 */
extern bool avr_piso_shift_register_read_bit(ShiftRegisterHandle shiftRegisterHandle);

/**
 * @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 shiftRegisterHandle 
 * @return byte 
 */
extern byte avr_piso_shift_register_read_byte(ShiftRegisterHandle shiftRegisterHandle);

/*******************************************************************************
 *                                                                             *
 *                                     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 ShiftRegisterHandle 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 shiftRegisterHandle
 */
extern void avr_sipo_shift_register_init(ShiftRegisterHandle shiftRegisterHandle);

/**
 * @brief Destroy and free SIPO shift register memory
 * 
 * @param shiftRegisterHandle 
 */
extern void avr_sipo_shift_register_destroy(ShiftRegisterHandle shiftRegisterHandle);

/**
 * @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 shiftRegisterHandle 
 */
extern void avr_sipo_shift_register_shift(ShiftRegisterHandle shiftRegisterHandle);

/**
 * @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 shiftRegisterHandle 
 * @param data 
 * @param position 
 */
extern void avr_sipo_shift_register_write_bit(ShiftRegisterHandle shiftRegisterHandle, 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 shiftRegisterHandle 
 * @param data 
 */
extern void avr_sipo_shift_register_write_byte(ShiftRegisterHandle shiftRegisterHandle, byte data);

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

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

/**
 * @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 shiftRegisterHandle 
 */
extern void avr_sipo_shift_register_push_data_to_output(ShiftRegisterHandle shiftRegisterHandle);

/**
 * @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 shiftRegisterHandle 
 */
extern void avr_sipo_shift_register_reset(ShiftRegisterHandle shiftRegisterHandle);

#endif