Example software for a Cyclic Executive
Dependencies: MCP23017 SDFileSystem WattBob_TextLCD mbed
Tasks.cpp@10:c0531edf4850, 2016-03-02 (annotated)
- Committer:
- sk398
- Date:
- Wed Mar 02 13:38:27 2016 +0000
- Revision:
- 10:c0531edf4850
- Parent:
- 9:46408a8dea0c
Final version - all operational
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
sk398 | 4:b85bc0d810e1 | 1 | /* ##################################################################### |
sk398 | 4:b85bc0d810e1 | 2 | Tasks.cpp |
sk398 | 4:b85bc0d810e1 | 3 | --------- |
sk398 | 4:b85bc0d810e1 | 4 | |
sk398 | 4:b85bc0d810e1 | 5 | Embedded Software - Assignment 2 |
sk398 | 4:b85bc0d810e1 | 6 | -------------------------------- |
sk398 | 4:b85bc0d810e1 | 7 | |
sk398 | 4:b85bc0d810e1 | 8 | Written by: Steven Kay |
sk398 | 4:b85bc0d810e1 | 9 | |
sk398 | 4:b85bc0d810e1 | 10 | Date: February 2016 |
sk398 | 4:b85bc0d810e1 | 11 | |
sk398 | 10:c0531edf4850 | 12 | Function: This code defines the operations of all of the |
sk398 | 10:c0531edf4850 | 13 | methods, or tasks used by the cyclic executive |
sk398 | 10:c0531edf4850 | 14 | |
sk398 | 4:b85bc0d810e1 | 15 | ##################################################################### */ |
sk398 | 2:22ebabd78084 | 16 | |
sk398 | 1:221d677fe0d3 | 17 | #include "mbed.h" |
sk398 | 1:221d677fe0d3 | 18 | #include "Tasks.h" |
sk398 | 1:221d677fe0d3 | 19 | |
sk398 | 1:221d677fe0d3 | 20 | /* ==================================== Task 1 ==================================== */ |
sk398 | 1:221d677fe0d3 | 21 | Task1::Task1(PinName squareWaveInPin) |
sk398 | 1:221d677fe0d3 | 22 | { |
sk398 | 10:c0531edf4850 | 23 | // Construct new DigitalIn object using the pin number provided |
sk398 | 9:46408a8dea0c | 24 | _squareWaveIn = new DigitalIn(squareWaveInPin); |
sk398 | 1:221d677fe0d3 | 25 | } |
sk398 | 1:221d677fe0d3 | 26 | |
sk398 | 4:b85bc0d810e1 | 27 | void Task1::MeasureFrequency() |
sk398 | 4:b85bc0d810e1 | 28 | { |
sk398 | 10:c0531edf4850 | 29 | // If pulse is initially low, wait until rising edge before starting timer |
sk398 | 10:c0531edf4850 | 30 | if(_squareWaveIn -> read() == LOW) |
sk398 | 10:c0531edf4850 | 31 | { |
sk398 | 10:c0531edf4850 | 32 | while(_squareWaveIn -> read() == LOW) |
sk398 | 10:c0531edf4850 | 33 | { |
sk398 | 10:c0531edf4850 | 34 | wait_us(SAMPLE_FREQ); |
sk398 | 10:c0531edf4850 | 35 | } |
sk398 | 10:c0531edf4850 | 36 | |
sk398 | 10:c0531edf4850 | 37 | _Task1Timer.start(); |
sk398 | 10:c0531edf4850 | 38 | |
sk398 | 10:c0531edf4850 | 39 | // Once timer has started, wait until falling edge before breaking and |
sk398 | 10:c0531edf4850 | 40 | // stopping timer |
sk398 | 10:c0531edf4850 | 41 | while(_squareWaveIn -> read() == HIGH) |
sk398 | 10:c0531edf4850 | 42 | { |
sk398 | 10:c0531edf4850 | 43 | wait_us(SAMPLE_FREQ); |
sk398 | 10:c0531edf4850 | 44 | } |
sk398 | 10:c0531edf4850 | 45 | } |
sk398 | 10:c0531edf4850 | 46 | |
sk398 | 10:c0531edf4850 | 47 | // If pulse is initially high, wait until falling edge before starting timer |
sk398 | 10:c0531edf4850 | 48 | else if(_squareWaveIn -> read()== HIGH) |
sk398 | 10:c0531edf4850 | 49 | { |
sk398 | 10:c0531edf4850 | 50 | while(_squareWaveIn -> read() == HIGH) |
sk398 | 10:c0531edf4850 | 51 | { |
sk398 | 10:c0531edf4850 | 52 | wait_us(SAMPLE_FREQ); |
sk398 | 10:c0531edf4850 | 53 | } |
sk398 | 10:c0531edf4850 | 54 | |
sk398 | 10:c0531edf4850 | 55 | _Task1Timer.start(); |
sk398 | 10:c0531edf4850 | 56 | |
sk398 | 10:c0531edf4850 | 57 | // Once timer has started, wait until rising edge before breaking and |
sk398 | 10:c0531edf4850 | 58 | // stopping timer |
sk398 | 10:c0531edf4850 | 59 | while(_squareWaveIn -> read() == LOW) |
sk398 | 10:c0531edf4850 | 60 | { |
sk398 | 10:c0531edf4850 | 61 | wait_us(SAMPLE_FREQ); |
sk398 | 10:c0531edf4850 | 62 | } |
sk398 | 10:c0531edf4850 | 63 | } |
sk398 | 10:c0531edf4850 | 64 | |
sk398 | 10:c0531edf4850 | 65 | // Stop timer after breaking while loop conditions |
sk398 | 4:b85bc0d810e1 | 66 | _Task1Timer.stop(); |
sk398 | 10:c0531edf4850 | 67 | |
sk398 | 10:c0531edf4850 | 68 | // Calculate frequency from timer (either high or low time) |
sk398 | 10:c0531edf4850 | 69 | // do this by multiplying the time by 2 (high + low time) and dividing it, |
sk398 | 10:c0531edf4850 | 70 | // converting it to a frequency |
sk398 | 10:c0531edf4850 | 71 | // Store frequency in private class field |
sk398 | 10:c0531edf4850 | 72 | Task1::measuredFrequency = (1000000/(2*_Task1Timer.read_us())); |
sk398 | 10:c0531edf4850 | 73 | |
sk398 | 10:c0531edf4850 | 74 | // Reset timer |
sk398 | 4:b85bc0d810e1 | 75 | _Task1Timer.reset(); |
sk398 | 10:c0531edf4850 | 76 | |
sk398 | 4:b85bc0d810e1 | 77 | } |
sk398 | 4:b85bc0d810e1 | 78 | |
sk398 | 4:b85bc0d810e1 | 79 | int Task1::ReadFrequency() |
sk398 | 4:b85bc0d810e1 | 80 | { |
sk398 | 10:c0531edf4850 | 81 | // Run private method to calculate the frequency |
sk398 | 10:c0531edf4850 | 82 | MeasureFrequency(); |
sk398 | 4:b85bc0d810e1 | 83 | |
sk398 | 10:c0531edf4850 | 84 | // Return private field showing the newest frequency calculation |
sk398 | 4:b85bc0d810e1 | 85 | return measuredFrequency; |
sk398 | 4:b85bc0d810e1 | 86 | } |
sk398 | 1:221d677fe0d3 | 87 | |
sk398 | 1:221d677fe0d3 | 88 | /* ==================================== Task 2 ==================================== */ |
sk398 | 1:221d677fe0d3 | 89 | Task2::Task2(PinName digitalInCheckPin) |
sk398 | 1:221d677fe0d3 | 90 | { |
sk398 | 10:c0531edf4850 | 91 | //Construct new DigitalIn object from provided pin |
sk398 | 3:c611b9bb5770 | 92 | _digitalInCheck = new DigitalIn(digitalInCheckPin); |
sk398 | 1:221d677fe0d3 | 93 | } |
sk398 | 3:c611b9bb5770 | 94 | |
sk398 | 3:c611b9bb5770 | 95 | bool Task2::digitalInState() |
sk398 | 3:c611b9bb5770 | 96 | { |
sk398 | 10:c0531edf4850 | 97 | // Check state of pin, returning a TRUE if high, false if LOW |
sk398 | 3:c611b9bb5770 | 98 | if(_digitalInCheck -> read()) |
sk398 | 3:c611b9bb5770 | 99 | { |
sk398 | 3:c611b9bb5770 | 100 | return TRUE; |
sk398 | 3:c611b9bb5770 | 101 | } |
sk398 | 3:c611b9bb5770 | 102 | else |
sk398 | 3:c611b9bb5770 | 103 | { |
sk398 | 3:c611b9bb5770 | 104 | return FALSE; |
sk398 | 3:c611b9bb5770 | 105 | } |
sk398 | 3:c611b9bb5770 | 106 | } |
sk398 | 3:c611b9bb5770 | 107 | |
sk398 | 1:221d677fe0d3 | 108 | |
sk398 | 1:221d677fe0d3 | 109 | /* ==================================== Task 3 ==================================== */ |
sk398 | 1:221d677fe0d3 | 110 | Task3::Task3(PinName WatchdogPin) |
sk398 | 1:221d677fe0d3 | 111 | { |
sk398 | 10:c0531edf4850 | 112 | // Construct new DigitalOut object using provided pin |
sk398 | 1:221d677fe0d3 | 113 | _Watchdog = new DigitalOut(WatchdogPin); |
sk398 | 1:221d677fe0d3 | 114 | } |
sk398 | 1:221d677fe0d3 | 115 | |
sk398 | 1:221d677fe0d3 | 116 | void Task3::OutputWatchdogPulse() |
sk398 | 1:221d677fe0d3 | 117 | { |
sk398 | 10:c0531edf4850 | 118 | // Produce a 15ms pulse when method called |
sk398 | 1:221d677fe0d3 | 119 | _Watchdog -> write(HIGH); |
sk398 | 1:221d677fe0d3 | 120 | wait_ms(WATCHDOG_PULSE_WIDTH); |
sk398 | 1:221d677fe0d3 | 121 | _Watchdog -> write(LOW); |
sk398 | 1:221d677fe0d3 | 122 | } |
sk398 | 1:221d677fe0d3 | 123 | |
sk398 | 1:221d677fe0d3 | 124 | |
sk398 | 3:c611b9bb5770 | 125 | /* ==================================== Task 4 ==================================== */ |
sk398 | 3:c611b9bb5770 | 126 | Task4::Task4(PinName Analog1Pin,PinName Analog2Pin) |
sk398 | 3:c611b9bb5770 | 127 | { |
sk398 | 10:c0531edf4850 | 128 | // Construct new AnalogIn objects from provided pins |
sk398 | 3:c611b9bb5770 | 129 | _AnalogIn1 = new AnalogIn(Analog1Pin); |
sk398 | 3:c611b9bb5770 | 130 | _AnalogIn2 = new AnalogIn(Analog2Pin); |
sk398 | 3:c611b9bb5770 | 131 | } |
sk398 | 3:c611b9bb5770 | 132 | |
sk398 | 3:c611b9bb5770 | 133 | float *Task4::returnAnalogReadings() |
sk398 | 3:c611b9bb5770 | 134 | { |
sk398 | 10:c0531edf4850 | 135 | // Declare local scope fields to retain current totals |
sk398 | 3:c611b9bb5770 | 136 | float readBuffer_1 = 0.0; |
sk398 | 3:c611b9bb5770 | 137 | float readBuffer_2 = 0.0; |
sk398 | 3:c611b9bb5770 | 138 | |
sk398 | 10:c0531edf4850 | 139 | // Read 4 samples from AnalogIn pins |
sk398 | 3:c611b9bb5770 | 140 | for(int readCount = 0;readCount < NUM_ANALOG_SAMPLES; readCount++) |
sk398 | 3:c611b9bb5770 | 141 | { |
sk398 | 10:c0531edf4850 | 142 | // Add to readBuffer with new weighted reading. |
sk398 | 10:c0531edf4850 | 143 | // 3.3v due to supply voltage |
sk398 | 10:c0531edf4850 | 144 | readBuffer_1 += ((_AnalogIn1 -> read())*V_SUPPLY); |
sk398 | 10:c0531edf4850 | 145 | readBuffer_2 += ((_AnalogIn2 -> read())*V_SUPPLY); |
sk398 | 3:c611b9bb5770 | 146 | } |
sk398 | 3:c611b9bb5770 | 147 | |
sk398 | 10:c0531edf4850 | 148 | // Construct local buffer |
sk398 | 10:c0531edf4850 | 149 | float outputBuffer[2]; |
sk398 | 10:c0531edf4850 | 150 | |
sk398 | 10:c0531edf4850 | 151 | // Construct elements in outputBuffer array as averaged sample |
sk398 | 3:c611b9bb5770 | 152 | outputBuffer[0] = readBuffer_1/NUM_ANALOG_SAMPLES; |
sk398 | 4:b85bc0d810e1 | 153 | outputBuffer[1] = readBuffer_2/NUM_ANALOG_SAMPLES; |
sk398 | 3:c611b9bb5770 | 154 | |
sk398 | 10:c0531edf4850 | 155 | // Construct pointer to return the initial element of the outputBuffer |
sk398 | 4:b85bc0d810e1 | 156 | float *outputBufferPtr =&outputBuffer[0]; |
sk398 | 10:c0531edf4850 | 157 | |
sk398 | 10:c0531edf4850 | 158 | // Return pointer to first element of outputBuffer |
sk398 | 3:c611b9bb5770 | 159 | return outputBufferPtr; |
sk398 | 3:c611b9bb5770 | 160 | } |
sk398 | 4:b85bc0d810e1 | 161 | |
sk398 | 4:b85bc0d810e1 | 162 | /* ==================================== Task 5 ==================================== */ |
sk398 | 5:250f51c80ac1 | 163 | Task5::Task5(PinName sda, PinName scl, int address) |
sk398 | 4:b85bc0d810e1 | 164 | { |
sk398 | 10:c0531edf4850 | 165 | // Declare and initialise the LCD display |
sk398 | 5:250f51c80ac1 | 166 | _par_port = new MCP23017(sda,scl,address); |
sk398 | 5:250f51c80ac1 | 167 | _lcd = new WattBob_TextLCD(_par_port); |
sk398 | 5:250f51c80ac1 | 168 | _par_port -> write_bit(1,BL_BIT); |
sk398 | 4:b85bc0d810e1 | 169 | } |
sk398 | 4:b85bc0d810e1 | 170 | |
sk398 | 6:ceda53939eb8 | 171 | void Task5::updateDisplay( int task1Param, |
sk398 | 6:ceda53939eb8 | 172 | int task2Param, |
sk398 | 6:ceda53939eb8 | 173 | int errorState, |
sk398 | 6:ceda53939eb8 | 174 | float task4Channel1, |
sk398 | 6:ceda53939eb8 | 175 | float task4Channel2 ) |
sk398 | 5:250f51c80ac1 | 176 | { |
sk398 | 10:c0531edf4850 | 177 | // Print standard expression using input fields |
sk398 | 5:250f51c80ac1 | 178 | _lcd -> cls(); |
sk398 | 5:250f51c80ac1 | 179 | _lcd -> locate(0,0); |
sk398 | 6:ceda53939eb8 | 180 | _lcd -> printf("F-%4dHz S1-%d E%d",task1Param,task2Param,errorState); |
sk398 | 5:250f51c80ac1 | 181 | _lcd -> locate(1,0); |
sk398 | 5:250f51c80ac1 | 182 | _lcd -> printf("C1-%1.2f C2-%1.2f ",task4Channel1,task4Channel2); |
sk398 | 5:250f51c80ac1 | 183 | } |
sk398 | 6:ceda53939eb8 | 184 | |
sk398 | 6:ceda53939eb8 | 185 | /* ==================================== Task 6 ==================================== */ |
sk398 | 6:ceda53939eb8 | 186 | int Task6::updateErrorCode(int switch_1, float analog1, float analog2) |
sk398 | 6:ceda53939eb8 | 187 | { |
sk398 | 10:c0531edf4850 | 188 | // Using input fields, conduct a logical equation7 |
sk398 | 10:c0531edf4850 | 189 | // returning CDTN_MET when true, CDTN_FAIL when false |
sk398 | 10:c0531edf4850 | 190 | if(switch_1 == HIGH && (analog1 > analog2)) |
sk398 | 10:c0531edf4850 | 191 | { |
sk398 | 10:c0531edf4850 | 192 | return ERROR_CODE_CDTN_MET; |
sk398 | 10:c0531edf4850 | 193 | } |
sk398 | 6:ceda53939eb8 | 194 | else |
sk398 | 10:c0531edf4850 | 195 | { |
sk398 | 10:c0531edf4850 | 196 | return ERROR_CODE_CDTN_FAIL; |
sk398 | 10:c0531edf4850 | 197 | } |
sk398 | 6:ceda53939eb8 | 198 | } |
sk398 | 6:ceda53939eb8 | 199 | |
sk398 | 6:ceda53939eb8 | 200 | /* ==================================== Task 5 ==================================== */ |
sk398 | 6:ceda53939eb8 | 201 | Task7::Task7( PinName mosi, |
sk398 | 6:ceda53939eb8 | 202 | PinName miso, |
sk398 | 6:ceda53939eb8 | 203 | PinName sck, |
sk398 | 6:ceda53939eb8 | 204 | PinName cs, |
sk398 | 6:ceda53939eb8 | 205 | const char *SDName, |
sk398 | 6:ceda53939eb8 | 206 | const char *dir ) |
sk398 | 6:ceda53939eb8 | 207 | { |
sk398 | 10:c0531edf4850 | 208 | // Construct new SDFileSystem object |
sk398 | 6:ceda53939eb8 | 209 | _sd = new SDFileSystem(mosi,miso,sck,cs, SDName); |
sk398 | 10:c0531edf4850 | 210 | |
sk398 | 10:c0531edf4850 | 211 | // Call private method to create default directory |
sk398 | 6:ceda53939eb8 | 212 | makeDirectory(dir); |
sk398 | 6:ceda53939eb8 | 213 | } |
sk398 | 6:ceda53939eb8 | 214 | |
sk398 | 6:ceda53939eb8 | 215 | void Task7::makeDirectory(const char *dir) |
sk398 | 6:ceda53939eb8 | 216 | { |
sk398 | 10:c0531edf4850 | 217 | // Create directory onto sd card |
sk398 | 6:ceda53939eb8 | 218 | mkdir(dir,0777); |
sk398 | 6:ceda53939eb8 | 219 | } |
sk398 | 6:ceda53939eb8 | 220 | |
sk398 | 6:ceda53939eb8 | 221 | int Task7::openFile(const char *dirFile,const char *accessType) |
sk398 | 6:ceda53939eb8 | 222 | { |
sk398 | 10:c0531edf4850 | 223 | // Create pointer to FILE object |
sk398 | 10:c0531edf4850 | 224 | Task7::fp = fopen(dirFile,accessType); |
sk398 | 10:c0531edf4850 | 225 | |
sk398 | 10:c0531edf4850 | 226 | // If failed to open file, return 1, indicating error, else return 0 |
sk398 | 10:c0531edf4850 | 227 | if(Task7::fp == NULL) |
sk398 | 6:ceda53939eb8 | 228 | { |
sk398 | 6:ceda53939eb8 | 229 | return 1; |
sk398 | 6:ceda53939eb8 | 230 | } |
sk398 | 6:ceda53939eb8 | 231 | return 0; |
sk398 | 6:ceda53939eb8 | 232 | } |
sk398 | 6:ceda53939eb8 | 233 | |
sk398 | 6:ceda53939eb8 | 234 | void Task7::writeData(const char *dataStream) |
sk398 | 6:ceda53939eb8 | 235 | { |
sk398 | 10:c0531edf4850 | 236 | // Print Stream of data to FILE object fp |
sk398 | 10:c0531edf4850 | 237 | fprintf(Task7::fp,dataStream); |
sk398 | 6:ceda53939eb8 | 238 | } |
sk398 | 6:ceda53939eb8 | 239 | |
sk398 | 6:ceda53939eb8 | 240 | void Task7::closeFile() |
sk398 | 6:ceda53939eb8 | 241 | { |
sk398 | 10:c0531edf4850 | 242 | // Close file located at fp |
sk398 | 10:c0531edf4850 | 243 | fclose(Task7::fp); |
sk398 | 6:ceda53939eb8 | 244 | } |