-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathSimpleGPIO_thread.cpp
executable file
·241 lines (216 loc) · 9.73 KB
/
SimpleGPIO_thread.cpp
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
#include "SimpleGPIO_thread.h"
/* ******************** Just some simple functions to set GPIO high or lo without a thread ********************/
SimpleGPIOStructPtr newThreadlessGPIO (int thePin, int polarity){ // returns a new SimpleGPIOStructPtr, ready to be used to control a single pin
// map GPIO peripheral, return nullPtr if it can't be mapped
volatile unsigned int * GPIOperiAddr = useGpioPeri ();
if (GPIOperiAddr == nullptr){
#if beVerbose
printf ("SimpleGPIO_threadMaker failed to map GPIO peripheral.\n");
#endif
return nullptr;
}
// make a new SimpleGPIOStruct which we fill out and return
SimpleGPIOStructPtr threadless = new SimpleGPIOStruct;
// save offsets to registers for setting pins high or lo
if (polarity == 0){ // low to high
threadless->GPIOperiHi = (unsigned int *) (GPIOperiAddr + 7);
threadless->GPIOperiLo = (unsigned int *) (GPIOperiAddr + 10);
}else{
threadless->GPIOperiHi = (unsigned int *) (GPIOperiAddr + 10);
threadless->GPIOperiLo = (unsigned int *) (GPIOperiAddr + 7);
}
// calculate pinBit
threadless->pinBit = 1 << thePin;
// initialize pin for output
*(GPIOperiAddr + (thePin /10)) &= ~(7<<((thePin %10)*3));
*(GPIOperiAddr + (thePin/10)) |= (1<<((thePin%10)*3));
// put pin in lo state to start
*(threadless->GPIOperiLo ) = threadless->pinBit ;
// return new threadless pointer
return threadless;
}
void setThreadlessGPIO (SimpleGPIOStructPtr threadless, int level){
if (level ==0){
*(threadless->GPIOperiLo) = threadless->pinBit;
}else{
*(threadless->GPIOperiHi) = threadless->pinBit;
}
}
/* *************************** Functions that are called from thread can not be class methods *********************
***************************************Initialization callback function ****************************************
Copies pinBit and set/unset register adressses to task data
last modified:
2018/02/09 by Jamie Boyd - copied some functionality over from thread make function
2018/02/01 by Jamie Boyd - initial version */
int SimpleGPIO_Init (void * initDataP, void * &taskDataP){
// task data pointer is a void pointer that needs to be initialized to a pointer to taskData and filled from our custom init structure
SimpleGPIOStructPtr taskData = new SimpleGPIOStruct;
taskDataP = taskData;
// initData is a pointer to our custom init structure
SimpleGPIOInitStructPtr initDataPtr = (SimpleGPIOInitStructPtr) initDataP;
// calculate address to ON and OFF register as Hi or Lo as appropriate to save a level of indirection later
if (initDataPtr->thePolarity == 1){ // High to Low pulses
taskData->GPIOperiHi = (unsigned int *) (initDataPtr->GPIOperiAddr + 10);
taskData->GPIOperiLo = (unsigned int *) initDataPtr->GPIOperiAddr+ 7;
}else{ // low to high pulses
taskData->GPIOperiHi = (unsigned int *) (initDataPtr->GPIOperiAddr + 7);
taskData->GPIOperiLo = (unsigned int *) (initDataPtr->GPIOperiAddr + 10);
}
// calculate pinBit
taskData->pinBit = 1 << initDataPtr->thePin;
// initialize pin for output
*(initDataPtr->GPIOperiAddr + ((initDataPtr->thePin) /10)) &= ~(7<<(((initDataPtr->thePin) %10)*3));
*(initDataPtr->GPIOperiAddr + ((initDataPtr->thePin)/10)) |= (1<<(((initDataPtr->thePin)%10)*3));
// put pin in selected start state
*(taskData->GPIOperiLo ) = taskData->pinBit ;
delete initDataPtr;
return 0; //
}
/* ***************** Lo Callback ******************************
Task to do on Low tick, sets GPIO line low or high depending on polarity
last modified:
2016/12/07 by Jamie Boyd - initial version */
void SimpleGPIO_Lo (void * taskData){
SimpleGPIOStructPtr gpioTaskPtr = (SimpleGPIOStructPtr) taskData;
*(gpioTaskPtr->GPIOperiLo) = gpioTaskPtr->pinBit;
}
/* ***************** Hi Callback ******************************
Task to do on High tick, sets GPIO line high or ow depending on polarity
last modified:
2016/12/07 by Jamie Boyd - initial version */
void SimpleGPIO_Hi (void * taskData){
SimpleGPIOStructPtr gpioTaskPtr = (SimpleGPIOStructPtr) taskData;
*(gpioTaskPtr->GPIOperiHi) =gpioTaskPtr->pinBit;
}
/* **************** Custom data mod callbacks *****************************
********************Changes GPIO pin bit********************************
modData is a pointer to an int for the new pin bit to use
last modified:
2018/02/02 by Jamie Boyd - initial version */
int SimpleGPIO_setPinCallback (void * modData, taskParams * theTask){
SimpleGPIOStructPtr gpioTaskPtr = (SimpleGPIOStructPtr)theTask->taskData;
int * pinBitPtr =(int *)modData;
gpioTaskPtr->pinBit = * pinBitPtr;
delete (pinBitPtr);
return 0;
}
/* ********************** Sets GPIO level by writing to the Hi or Lo address, as appropriate *************************
modData is a pointer to an int, 0 for low function, non-zero for high function. If polarity of pulse is reversed,
so also will be notion of setting hi vs setting lo .
last modified:
2018/02/02 by Jamie Boyd - initial version */
int SimpleGPIO_setLevelCallBack (void * modData, taskParams * theTask){
int * theLevel = (int *)modData;
SimpleGPIOStructPtr gpioTaskPtr = (SimpleGPIOStructPtr)theTask->taskData;
if (*theLevel ==0){
*(gpioTaskPtr->GPIOperiLo) = gpioTaskPtr->pinBit;
}else{
*(gpioTaskPtr->GPIOperiHi) = gpioTaskPtr->pinBit;
}
delete (theLevel);
return 0;
}
/* ****************************** Custom delete Function *****************************************************/
void SimpleGPIO_delTask (void * taskData){
SimpleGPIOStructPtr gpioTaskPtr = (SimpleGPIOStructPtr) taskData;
delete (gpioTaskPtr);
}
/* ******************************** SimpleGPIO_thread Class Methods *******************************************************
******************** ThreadMaker with Integer pulse duration, delay, and number of pulses timing description inputs ********************
Last Modified:
2018/02/28 by Jamie Boyd - removed init, high, and low functions in call to constructor, as we call superclass construcor with same 3 functions every time
2018/02/09 by jamie Boyd - moved some functionality into init function and constructor
2018/02/01 by Jamie Boyd - Initial Version */
SimpleGPIO_thread * SimpleGPIO_thread::SimpleGPIO_threadMaker (int pin, int polarity, unsigned int delayUsecs, unsigned int durUsecs, unsigned int nPulses, int accuracyLevel) {
// make and fill an init struct
SimpleGPIOInitStructPtr initStruct = new SimpleGPIOInitStruct;
initStruct->thePin = pin;
initStruct->thePolarity = polarity;
initStruct->GPIOperiAddr = useGpioPeri ();
if (initStruct->GPIOperiAddr == nullptr){
#if beVerbose
printf ("SimpleGPIO_threadMaker failed to map GPIO peripheral.\n");
#endif
return nullptr;
}
int errCode =0;
// call SimpleGPIO_thread constructor, which calls pulsedThread contructor
SimpleGPIO_thread * newGPIO_thread = new SimpleGPIO_thread (pin, polarity, delayUsecs, durUsecs, nPulses, (void *) initStruct, &SimpleGPIO_Init, accuracyLevel, errCode);
if (errCode){
#if beVerbose
printf ("SimpleGPIO_threadMaker failed to make SimpleGPIO_thread.\n");
#endif
return nullptr;
}
// set custom task delete function
newGPIO_thread->setTaskDataDelFunc (&SimpleGPIO_delTask);
return newGPIO_thread;
}
/* ******************* ThreadMaker with floating point frequency, duration, and duty cycle timing description inputs ********************
Last Modified:
2018/02/28 by Jamie Boyd - removed init, high, and low functions in call to constructor, as we call superclass construcor with same 3 functions every time
2018/02/09 by jamie Boyd - moved some functionality into initfunction and constructor
2018/02/01 by Jamie Boyd - Initial Version */
SimpleGPIO_thread * SimpleGPIO_thread::SimpleGPIO_threadMaker (int pin, int polarity, float frequency, float dutyCycle, float trainDuration, int accuracyLevel){
// make and fill an init struct
SimpleGPIOInitStructPtr initStruct = new SimpleGPIOInitStruct;
initStruct->thePin = pin;
initStruct->thePolarity = polarity;
initStruct->GPIOperiAddr = useGpioPeri ();
if (initStruct->GPIOperiAddr == nullptr){
#if beVerbose
printf ("SimpleGPIO_threadMaker failed to map GPIO peripheral.\n");
#endif
return nullptr;
}
int errCode =0;
// call SimpleGPIO_thread constructor, which calls pulsedThread contructor
SimpleGPIO_thread * newGPIO_thread = new SimpleGPIO_thread (pin, polarity, frequency, dutyCycle, trainDuration, (void *)initStruct, &SimpleGPIO_Init, accuracyLevel, errCode);
if (errCode){
#if beVerbose
printf ("Failed to make pulsed thread.\n");
#endif
return nullptr;
}
// set custom delete function for task data
newGPIO_thread->setTaskDataDelFunc (&SimpleGPIO_delTask);
return newGPIO_thread;
}
/* ****************************** Destructor handles GPIO peripheral mapping*************************
Thread data is destroyed by the pulsedThread destructor. All we need to do here is take care of GPIO peripheral mapping
Last Modified:
2018/02/01 by Jamie Boyd - Initial Version */
SimpleGPIO_thread::~SimpleGPIO_thread (){
//unUseGPIOperi();
}
/* ****************************** utility functions - setters and getters *************************
************************************sets pin bit in task structure by installing custom modifier function
Last Modified:
2018/02/02 by Jamie Boyd - Initial Version */
int SimpleGPIO_thread::setPin (int newPin, int isLocking){
pinNumber = newPin;
int * newPinVal = new int;
* newPinVal = 1 << newPin;
int returnVal = modCustom (&SimpleGPIO_setPinCallback, (void *) newPinVal, isLocking);
return returnVal;
}
int SimpleGPIO_thread::getPin (void){
return pinNumber;
}
int SimpleGPIO_thread::getPolarity (void){
return polarity;
}
int SimpleGPIO_thread::setLevel (int level, int isLocking){
int * setlevelPtr= new int;
if (polarity == 0){
* setlevelPtr = level ;
}else{
if (level == 0){
* setlevelPtr = 1;
}else{
* setlevelPtr = 0;
}
}
int returnVal = modCustom (&SimpleGPIO_setLevelCallBack, (void *) setlevelPtr, isLocking);
return returnVal;
}