Shengyuan Chu
/
AngleMeter
Simple Electronic Angle Meter and Spirit Level.
main.cpp@1:f167423f6f0c, 2015-05-11 (annotated)
- Committer:
- chushengyuan
- Date:
- Mon May 11 13:15:33 2015 +0000
- Revision:
- 1:f167423f6f0c
- Parent:
- 0:2885d4453e88
Final
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
chushengyuan | 0:2885d4453e88 | 1 | /** |
chushengyuan | 0:2885d4453e88 | 2 | @file main.cpp |
chushengyuan | 1:f167423f6f0c | 3 | @brief Electronic Angle Meter and Spirit Level. |
chushengyuan | 0:2885d4453e88 | 4 | @brief Revision 1.0. |
chushengyuan | 0:2885d4453e88 | 5 | @author Shengyuan Chu |
chushengyuan | 0:2885d4453e88 | 6 | @date May 2015 |
chushengyuan | 0:2885d4453e88 | 7 | */ |
chushengyuan | 0:2885d4453e88 | 8 | |
chushengyuan | 0:2885d4453e88 | 9 | #include "mbed.h" |
chushengyuan | 0:2885d4453e88 | 10 | #include "main.h" |
chushengyuan | 0:2885d4453e88 | 11 | #include "MMA8452.h" |
chushengyuan | 0:2885d4453e88 | 12 | #include "PowerControl/PowerControl.h" |
chushengyuan | 0:2885d4453e88 | 13 | #include "PowerControl/EthernetPowerControl.h" |
chushengyuan | 0:2885d4453e88 | 14 | |
chushengyuan | 0:2885d4453e88 | 15 | /** |
chushengyuan | 0:2885d4453e88 | 16 | @brief Connect all components to mbed LPC1768. |
chushengyuan | 0:2885d4453e88 | 17 | @brief Connect LCD to pin 7,8,9,10,11,13,26. |
chushengyuan | 0:2885d4453e88 | 18 | @brief Connect Accelerometer to pin 27,28. |
chushengyuan | 0:2885d4453e88 | 19 | @brief Connect buzzer to pin 21. |
chushengyuan | 0:2885d4453e88 | 20 | @brief Connect button to pin 17. |
chushengyuan | 0:2885d4453e88 | 21 | @brief Connect LEDs to pin 22,23,24,25. |
chushengyuan | 0:2885d4453e88 | 22 | */ |
chushengyuan | 0:2885d4453e88 | 23 | N5110 lcd(p7,p8,p9,p10,p11,p13,p26); |
chushengyuan | 0:2885d4453e88 | 24 | MMA8452 mma8452(p28,p27); |
chushengyuan | 0:2885d4453e88 | 25 | PwmOut buzzer(p21); |
chushengyuan | 0:2885d4453e88 | 26 | DigitalIn pb(p17); |
chushengyuan | 0:2885d4453e88 | 27 | DigitalOut ledA(p25); |
chushengyuan | 0:2885d4453e88 | 28 | DigitalOut ledB(p23); |
chushengyuan | 0:2885d4453e88 | 29 | DigitalOut ledC(p22); |
chushengyuan | 0:2885d4453e88 | 30 | DigitalOut ledD(p24); |
chushengyuan | 0:2885d4453e88 | 31 | |
chushengyuan | 0:2885d4453e88 | 32 | Serial serial(USBTX,USBRX); |
chushengyuan | 0:2885d4453e88 | 33 | Timeout flipper; |
chushengyuan | 0:2885d4453e88 | 34 | |
chushengyuan | 0:2885d4453e88 | 35 | /** |
chushengyuan | 0:2885d4453e88 | 36 | @brief Function prototypes. |
chushengyuan | 0:2885d4453e88 | 37 | */ |
chushengyuan | 0:2885d4453e88 | 38 | void Switch (int functoion); |
chushengyuan | 0:2885d4453e88 | 39 | void AngleMeter(); |
chushengyuan | 1:f167423f6f0c | 40 | void SpiritLevel(); |
chushengyuan | 0:2885d4453e88 | 41 | void fun1(); |
chushengyuan | 0:2885d4453e88 | 42 | void fun2(); |
chushengyuan | 0:2885d4453e88 | 43 | |
chushengyuan | 0:2885d4453e88 | 44 | /** |
chushengyuan | 0:2885d4453e88 | 45 | @brief Different frequencies of buzzer. |
chushengyuan | 0:2885d4453e88 | 46 | */ |
chushengyuan | 1:f167423f6f0c | 47 | float frequency1 = 1046.5; |
chushengyuan | 1:f167423f6f0c | 48 | float frequency2 = 1174.7; |
chushengyuan | 1:f167423f6f0c | 49 | float frequency3 = 1318.5; |
chushengyuan | 0:2885d4453e88 | 50 | |
chushengyuan | 0:2885d4453e88 | 51 | /** |
chushengyuan | 0:2885d4453e88 | 52 | @brief Main function. |
chushengyuan | 0:2885d4453e88 | 53 | @brief Call function of Angle Meter without pushing |
chushengyuan | 0:2885d4453e88 | 54 | @brief button when power is initally turned on. |
chushengyuan | 0:2885d4453e88 | 55 | */ |
chushengyuan | 0:2885d4453e88 | 56 | int main() { |
chushengyuan | 0:2885d4453e88 | 57 | |
chushengyuan | 0:2885d4453e88 | 58 | /**Power down Ethernet interface to save power.*/ |
chushengyuan | 0:2885d4453e88 | 59 | PHY_PowerDown(); |
chushengyuan | 0:2885d4453e88 | 60 | |
chushengyuan | 0:2885d4453e88 | 61 | /**Initialise LCD and set brightness to 0.8.*/ |
chushengyuan | 0:2885d4453e88 | 62 | lcd.init(); |
chushengyuan | 0:2885d4453e88 | 63 | lcd.normalMode(); |
chushengyuan | 0:2885d4453e88 | 64 | lcd.setBrightness(0.8); |
chushengyuan | 0:2885d4453e88 | 65 | |
chushengyuan | 0:2885d4453e88 | 66 | /**Display the name of Angle Meter function after the initialization of LCD.*/ |
chushengyuan | 0:2885d4453e88 | 67 | lcd.printString("Electronic",12,2); |
chushengyuan | 0:2885d4453e88 | 68 | lcd.printString("Angle Meter",10,3); |
chushengyuan | 0:2885d4453e88 | 69 | |
chushengyuan | 0:2885d4453e88 | 70 | /**Call function of Angle Meter after 2 seconds' delay.*/ |
chushengyuan | 0:2885d4453e88 | 71 | flipper.attach(&AngleMeter, 2.0); |
chushengyuan | 0:2885d4453e88 | 72 | |
chushengyuan | 0:2885d4453e88 | 73 | /**Turn all the LEDs on when the power is initially turned on.*/ |
chushengyuan | 0:2885d4453e88 | 74 | ledA=1; |
chushengyuan | 0:2885d4453e88 | 75 | ledB=1; |
chushengyuan | 0:2885d4453e88 | 76 | ledC=1; |
chushengyuan | 0:2885d4453e88 | 77 | ledD=1; |
chushengyuan | 0:2885d4453e88 | 78 | |
chushengyuan | 0:2885d4453e88 | 79 | /**Set button to PullDown mode.*/ |
chushengyuan | 0:2885d4453e88 | 80 | pb.mode(PullDown); |
chushengyuan | 0:2885d4453e88 | 81 | |
chushengyuan | 0:2885d4453e88 | 82 | /**Change the integer between 1 and 2 when button is pressed and send it to Switch function.*/ |
chushengyuan | 0:2885d4453e88 | 83 | int function = 1; |
chushengyuan | 0:2885d4453e88 | 84 | |
chushengyuan | 0:2885d4453e88 | 85 | while(1) { |
chushengyuan | 0:2885d4453e88 | 86 | if (pb){ |
chushengyuan | 0:2885d4453e88 | 87 | Switch(function); |
chushengyuan | 0:2885d4453e88 | 88 | |
chushengyuan | 0:2885d4453e88 | 89 | /**Allow 0.2 second for button debounce.*/ |
chushengyuan | 0:2885d4453e88 | 90 | wait(0.2); |
chushengyuan | 0:2885d4453e88 | 91 | while (pb); |
chushengyuan | 0:2885d4453e88 | 92 | {if (function == 2) function = 1; else function++;} |
chushengyuan | 0:2885d4453e88 | 93 | } |
chushengyuan | 0:2885d4453e88 | 94 | } |
chushengyuan | 0:2885d4453e88 | 95 | } |
chushengyuan | 0:2885d4453e88 | 96 | |
chushengyuan | 0:2885d4453e88 | 97 | /** |
chushengyuan | 1:f167423f6f0c | 98 | @brief Switch functions between Angle Meter and Spirit Level. |
chushengyuan | 0:2885d4453e88 | 99 | @param function - integer to change between 1 and 2. |
chushengyuan | 0:2885d4453e88 | 100 | @return Call fun1() when function=2, call fun2() when function=1. |
chushengyuan | 0:2885d4453e88 | 101 | */ |
chushengyuan | 0:2885d4453e88 | 102 | void Switch (int function) |
chushengyuan | 0:2885d4453e88 | 103 | { |
chushengyuan | 0:2885d4453e88 | 104 | |
chushengyuan | 0:2885d4453e88 | 105 | switch (function) { |
chushengyuan | 0:2885d4453e88 | 106 | case 1 : fun2(); |
chushengyuan | 0:2885d4453e88 | 107 | break; |
chushengyuan | 0:2885d4453e88 | 108 | case 2 : fun1(); |
chushengyuan | 0:2885d4453e88 | 109 | break; |
chushengyuan | 0:2885d4453e88 | 110 | } |
chushengyuan | 0:2885d4453e88 | 111 | |
chushengyuan | 0:2885d4453e88 | 112 | } |
chushengyuan | 0:2885d4453e88 | 113 | |
chushengyuan | 0:2885d4453e88 | 114 | /** |
chushengyuan | 0:2885d4453e88 | 115 | @brief Display angles in two dimensions and indicate directions using arrows. |
chushengyuan | 0:2885d4453e88 | 116 | */ |
chushengyuan | 0:2885d4453e88 | 117 | void AngleMeter() |
chushengyuan | 0:2885d4453e88 | 118 | { |
chushengyuan | 0:2885d4453e88 | 119 | /**Initialise the accelerometer.*/ |
chushengyuan | 0:2885d4453e88 | 120 | mma8452.init(); |
chushengyuan | 0:2885d4453e88 | 121 | Acceleration acceleration; |
chushengyuan | 0:2885d4453e88 | 122 | |
chushengyuan | 0:2885d4453e88 | 123 | /**Lower down the brightness of LCD to 0.5.*/ |
chushengyuan | 0:2885d4453e88 | 124 | lcd.clear(); |
chushengyuan | 0:2885d4453e88 | 125 | lcd.setBrightness(0.5); |
chushengyuan | 0:2885d4453e88 | 126 | |
chushengyuan | 0:2885d4453e88 | 127 | /**When button is not pushed, main features of Angle Meter will be run.*/ |
chushengyuan | 0:2885d4453e88 | 128 | while(!pb) { |
chushengyuan | 0:2885d4453e88 | 129 | |
chushengyuan | 0:2885d4453e88 | 130 | /**Display 'degree' in the last line of LCD.*/ |
chushengyuan | 0:2885d4453e88 | 131 | lcd.printString("degree",3,5); |
chushengyuan | 0:2885d4453e88 | 132 | lcd.printString("degree",46,5); |
chushengyuan | 0:2885d4453e88 | 133 | |
chushengyuan | 0:2885d4453e88 | 134 | /**Read value of acceleration.*/ |
chushengyuan | 0:2885d4453e88 | 135 | acceleration = mma8452.readValues(); |
chushengyuan | 0:2885d4453e88 | 136 | |
chushengyuan | 0:2885d4453e88 | 137 | float X=acceleration.x; |
chushengyuan | 0:2885d4453e88 | 138 | float Y=acceleration.y; |
chushengyuan | 0:2885d4453e88 | 139 | float Z=acceleration.z; |
chushengyuan | 0:2885d4453e88 | 140 | |
chushengyuan | 0:2885d4453e88 | 141 | /**Calculate the angles in X and Y dimensions.*/ |
chushengyuan | 0:2885d4453e88 | 142 | float Ax=atan(X/sqrt(pow(Y,2)+pow(Z,2)))/3.14159265358979323846*180; |
chushengyuan | 0:2885d4453e88 | 143 | float Ay=atan(Y/sqrt(pow(X,2)+pow(Z,2)))/3.14159265358979323846*180; |
chushengyuan | 0:2885d4453e88 | 144 | |
chushengyuan | 0:2885d4453e88 | 145 | /**Print formatted data to buffer.*/ |
chushengyuan | 0:2885d4453e88 | 146 | char buffer1[14]; |
chushengyuan | 0:2885d4453e88 | 147 | int length = sprintf(buffer1,"%.0f",abs(Ax)); |
chushengyuan | 0:2885d4453e88 | 148 | char buffer2[14]; |
chushengyuan | 0:2885d4453e88 | 149 | length = sprintf(buffer2,"%.0f",abs(Ay)); |
chushengyuan | 0:2885d4453e88 | 150 | |
chushengyuan | 0:2885d4453e88 | 151 | /**Display values if string will fit on display.*/ |
chushengyuan | 0:2885d4453e88 | 152 | if (length <= 14) // |
chushengyuan | 0:2885d4453e88 | 153 | lcd.printString(buffer1,20,3); |
chushengyuan | 0:2885d4453e88 | 154 | lcd.printString(buffer2,55,3); |
chushengyuan | 0:2885d4453e88 | 155 | |
chushengyuan | 0:2885d4453e88 | 156 | /**LED C will be turned on if the angle in X dimension is larger than 20 degree.*/ |
chushengyuan | 0:2885d4453e88 | 157 | if (Ax>20) |
chushengyuan | 0:2885d4453e88 | 158 | ledC=1; |
chushengyuan | 0:2885d4453e88 | 159 | else |
chushengyuan | 0:2885d4453e88 | 160 | ledC=0; |
chushengyuan | 0:2885d4453e88 | 161 | |
chushengyuan | 0:2885d4453e88 | 162 | /**LED A will be turned on if the angle in X dimension is smaller than -20 degree.*/ |
chushengyuan | 0:2885d4453e88 | 163 | if (Ax<-20) |
chushengyuan | 0:2885d4453e88 | 164 | ledA=1; |
chushengyuan | 0:2885d4453e88 | 165 | else |
chushengyuan | 0:2885d4453e88 | 166 | ledA=0; |
chushengyuan | 0:2885d4453e88 | 167 | |
chushengyuan | 0:2885d4453e88 | 168 | /**LED D will be turned on if the angle in Y dimension is larger than 20 degree.*/ |
chushengyuan | 0:2885d4453e88 | 169 | if (Ay>20) |
chushengyuan | 0:2885d4453e88 | 170 | ledD=1; |
chushengyuan | 0:2885d4453e88 | 171 | else |
chushengyuan | 0:2885d4453e88 | 172 | ledD=0; |
chushengyuan | 0:2885d4453e88 | 173 | |
chushengyuan | 0:2885d4453e88 | 174 | /**LED B will be turned on if the angle in Y dimension is smaller than -20 degree.*/ |
chushengyuan | 0:2885d4453e88 | 175 | if (Ay<-20) |
chushengyuan | 0:2885d4453e88 | 176 | ledB=1; |
chushengyuan | 0:2885d4453e88 | 177 | else |
chushengyuan | 0:2885d4453e88 | 178 | ledB=0; |
chushengyuan | 0:2885d4453e88 | 179 | |
chushengyuan | 0:2885d4453e88 | 180 | /**Draw lines of the body of arrows.*/ |
chushengyuan | 0:2885d4453e88 | 181 | lcd.drawLine(58,6,58,16,1); |
chushengyuan | 0:2885d4453e88 | 182 | lcd.drawLine(17,11,29,11,1); |
chushengyuan | 0:2885d4453e88 | 183 | lcd.refresh(); |
chushengyuan | 0:2885d4453e88 | 184 | |
chushengyuan | 0:2885d4453e88 | 185 | /**Pixes will be set if the angle in Y dimension is larger than 0 degree.*/ |
chushengyuan | 0:2885d4453e88 | 186 | if (Ay>=0){ |
chushengyuan | 0:2885d4453e88 | 187 | lcd.setPixel(60,5); |
chushengyuan | 0:2885d4453e88 | 188 | lcd.setPixel(59,5); |
chushengyuan | 0:2885d4453e88 | 189 | lcd.setPixel(58,5); |
chushengyuan | 0:2885d4453e88 | 190 | lcd.setPixel(57,5); |
chushengyuan | 0:2885d4453e88 | 191 | lcd.setPixel(56,5); |
chushengyuan | 0:2885d4453e88 | 192 | lcd.setPixel(59,4); |
chushengyuan | 0:2885d4453e88 | 193 | lcd.setPixel(58,4); |
chushengyuan | 0:2885d4453e88 | 194 | lcd.setPixel(57,4); |
chushengyuan | 0:2885d4453e88 | 195 | lcd.setPixel(58,3); |
chushengyuan | 0:2885d4453e88 | 196 | lcd.refresh(); |
chushengyuan | 0:2885d4453e88 | 197 | } |
chushengyuan | 0:2885d4453e88 | 198 | |
chushengyuan | 0:2885d4453e88 | 199 | /**Pixes will be set if the angle in Y dimension is smaller than 0 degree.*/ |
chushengyuan | 0:2885d4453e88 | 200 | else if (Ay<=0) { |
chushengyuan | 0:2885d4453e88 | 201 | lcd.setPixel(60,17); |
chushengyuan | 0:2885d4453e88 | 202 | lcd.setPixel(59,17); |
chushengyuan | 0:2885d4453e88 | 203 | lcd.setPixel(58,17); |
chushengyuan | 0:2885d4453e88 | 204 | lcd.setPixel(57,17); |
chushengyuan | 0:2885d4453e88 | 205 | lcd.setPixel(56,17); |
chushengyuan | 0:2885d4453e88 | 206 | lcd.setPixel(59,18); |
chushengyuan | 0:2885d4453e88 | 207 | lcd.setPixel(58,18); |
chushengyuan | 0:2885d4453e88 | 208 | lcd.setPixel(57,18); |
chushengyuan | 0:2885d4453e88 | 209 | lcd.setPixel(58,19); |
chushengyuan | 0:2885d4453e88 | 210 | lcd.refresh(); |
chushengyuan | 0:2885d4453e88 | 211 | } |
chushengyuan | 0:2885d4453e88 | 212 | |
chushengyuan | 0:2885d4453e88 | 213 | /**Pixes will be set if the angle in X dimension is larger than 0 degree.*/ |
chushengyuan | 0:2885d4453e88 | 214 | if (Ax>=0) { |
chushengyuan | 0:2885d4453e88 | 215 | lcd.setPixel(30,13); |
chushengyuan | 0:2885d4453e88 | 216 | lcd.setPixel(30,12); |
chushengyuan | 0:2885d4453e88 | 217 | lcd.setPixel(30,11); |
chushengyuan | 0:2885d4453e88 | 218 | lcd.setPixel(30,10); |
chushengyuan | 0:2885d4453e88 | 219 | lcd.setPixel(30,9); |
chushengyuan | 0:2885d4453e88 | 220 | lcd.setPixel(31,12); |
chushengyuan | 0:2885d4453e88 | 221 | lcd.setPixel(31,11); |
chushengyuan | 0:2885d4453e88 | 222 | lcd.setPixel(31,10); |
chushengyuan | 0:2885d4453e88 | 223 | lcd.setPixel(32,11); |
chushengyuan | 0:2885d4453e88 | 224 | lcd.refresh(); |
chushengyuan | 0:2885d4453e88 | 225 | } |
chushengyuan | 0:2885d4453e88 | 226 | |
chushengyuan | 0:2885d4453e88 | 227 | /**Pixes will be set if the angle in X dimension is smaller than 0 degree.*/ |
chushengyuan | 0:2885d4453e88 | 228 | else if (Ax<=0) { |
chushengyuan | 0:2885d4453e88 | 229 | lcd.setPixel(16,13); |
chushengyuan | 0:2885d4453e88 | 230 | lcd.setPixel(16,12); |
chushengyuan | 0:2885d4453e88 | 231 | lcd.setPixel(16,11); |
chushengyuan | 0:2885d4453e88 | 232 | lcd.setPixel(16,10); |
chushengyuan | 0:2885d4453e88 | 233 | lcd.setPixel(16,9); |
chushengyuan | 0:2885d4453e88 | 234 | lcd.setPixel(15,12); |
chushengyuan | 0:2885d4453e88 | 235 | lcd.setPixel(15,11); |
chushengyuan | 0:2885d4453e88 | 236 | lcd.setPixel(15,10); |
chushengyuan | 0:2885d4453e88 | 237 | lcd.setPixel(14,11); |
chushengyuan | 0:2885d4453e88 | 238 | lcd.refresh(); |
chushengyuan | 0:2885d4453e88 | 239 | } |
chushengyuan | 0:2885d4453e88 | 240 | |
chushengyuan | 0:2885d4453e88 | 241 | /**Decrease the fluctuation of values.*/ |
chushengyuan | 0:2885d4453e88 | 242 | wait(0.3); |
chushengyuan | 0:2885d4453e88 | 243 | lcd.clear(); |
chushengyuan | 0:2885d4453e88 | 244 | |
chushengyuan | 0:2885d4453e88 | 245 | /**Buzzer will beep in frequency 2 if the angle is between 50 and 75 degree.*/ |
chushengyuan | 0:2885d4453e88 | 246 | if ((abs(Ax) >= 50 && abs(Ax) < 75)||(abs(Ay) >= 50 && abs(Ay) < 75)) { |
chushengyuan | 0:2885d4453e88 | 247 | buzzer.period(1/frequency2); |
chushengyuan | 0:2885d4453e88 | 248 | buzzer=0.1; |
chushengyuan | 0:2885d4453e88 | 249 | } |
chushengyuan | 0:2885d4453e88 | 250 | |
chushengyuan | 0:2885d4453e88 | 251 | /**Buzzer will beep in frequency 3 if the angle is beyond 75 degree.*/ |
chushengyuan | 0:2885d4453e88 | 252 | else if ((abs(Ax) >= 75)||(abs(Ay) >= 75)) { |
chushengyuan | 0:2885d4453e88 | 253 | buzzer.period(1/frequency3); |
chushengyuan | 0:2885d4453e88 | 254 | buzzer=0.1; |
chushengyuan | 0:2885d4453e88 | 255 | } |
chushengyuan | 0:2885d4453e88 | 256 | |
chushengyuan | 0:2885d4453e88 | 257 | /**Buzzer will not beep.*/ |
chushengyuan | 0:2885d4453e88 | 258 | else { |
chushengyuan | 0:2885d4453e88 | 259 | buzzer.period(1/frequency1); |
chushengyuan | 0:2885d4453e88 | 260 | buzzer=0; |
chushengyuan | 0:2885d4453e88 | 261 | } |
chushengyuan | 0:2885d4453e88 | 262 | } |
chushengyuan | 0:2885d4453e88 | 263 | |
chushengyuan | 0:2885d4453e88 | 264 | /**When button is pushed, main features will stop.*/ |
chushengyuan | 0:2885d4453e88 | 265 | while(pb) { |
chushengyuan | 0:2885d4453e88 | 266 | break; |
chushengyuan | 0:2885d4453e88 | 267 | } |
chushengyuan | 0:2885d4453e88 | 268 | } |
chushengyuan | 0:2885d4453e88 | 269 | |
chushengyuan | 0:2885d4453e88 | 270 | /** |
chushengyuan | 0:2885d4453e88 | 271 | @brief Indicate the gradient in all directions by showing |
chushengyuan | 0:2885d4453e88 | 272 | @brief the position of a group of pixes. |
chushengyuan | 0:2885d4453e88 | 273 | */ |
chushengyuan | 1:f167423f6f0c | 274 | void SpiritLevel() |
chushengyuan | 0:2885d4453e88 | 275 | { |
chushengyuan | 0:2885d4453e88 | 276 | /**Initialise all the LEDs to be off.*/ |
chushengyuan | 0:2885d4453e88 | 277 | ledA=0; |
chushengyuan | 0:2885d4453e88 | 278 | ledB=0; |
chushengyuan | 0:2885d4453e88 | 279 | ledC=0; |
chushengyuan | 0:2885d4453e88 | 280 | ledD=0; |
chushengyuan | 0:2885d4453e88 | 281 | |
chushengyuan | 0:2885d4453e88 | 282 | /**Set the LCD to inverse mode and lower down the brightness to 0.5.*/ |
chushengyuan | 0:2885d4453e88 | 283 | lcd.clear(); |
chushengyuan | 0:2885d4453e88 | 284 | lcd.inverseMode(); |
chushengyuan | 0:2885d4453e88 | 285 | lcd.setBrightness(0.5); |
chushengyuan | 0:2885d4453e88 | 286 | |
chushengyuan | 0:2885d4453e88 | 287 | /**Initialise the accelerometer.*/ |
chushengyuan | 0:2885d4453e88 | 288 | mma8452.init(); |
chushengyuan | 0:2885d4453e88 | 289 | Acceleration acceleration; |
chushengyuan | 0:2885d4453e88 | 290 | |
chushengyuan | 1:f167423f6f0c | 291 | /**When button is not pushed, main features of Spirit Level will be run.*/ |
chushengyuan | 0:2885d4453e88 | 292 | while(!pb) { |
chushengyuan | 0:2885d4453e88 | 293 | |
chushengyuan | 0:2885d4453e88 | 294 | /**Read value of acceleration.*/ |
chushengyuan | 0:2885d4453e88 | 295 | acceleration = mma8452.readValues();//read value of acceleration |
chushengyuan | 0:2885d4453e88 | 296 | |
chushengyuan | 0:2885d4453e88 | 297 | float Ax=acceleration.x; |
chushengyuan | 0:2885d4453e88 | 298 | float Ay=acceleration.y; |
chushengyuan | 0:2885d4453e88 | 299 | |
chushengyuan | 0:2885d4453e88 | 300 | /**Draw three circles and two lines.*/ |
chushengyuan | 0:2885d4453e88 | 301 | lcd.drawCircle(41,24,23,0); |
chushengyuan | 0:2885d4453e88 | 302 | lcd.drawCircle(41,24,4,0); |
chushengyuan | 0:2885d4453e88 | 303 | lcd.drawCircle(41,24,13,0); |
chushengyuan | 0:2885d4453e88 | 304 | lcd.drawLine(41,3,41,45,1); |
chushengyuan | 0:2885d4453e88 | 305 | lcd.drawLine(20,24,62,24,1); |
chushengyuan | 0:2885d4453e88 | 306 | lcd.refresh(); |
chushengyuan | 0:2885d4453e88 | 307 | |
chushengyuan | 0:2885d4453e88 | 308 | /**Pixes will be displayed if acceleration values are within -0.4 and 0.4.*/ |
chushengyuan | 0:2885d4453e88 | 309 | if (abs(Ax)<=0.4&&abs(Ay)<=0.4) { |
chushengyuan | 0:2885d4453e88 | 310 | |
chushengyuan | 0:2885d4453e88 | 311 | float X=Ax/0.018; |
chushengyuan | 0:2885d4453e88 | 312 | float Y=Ay/0.018; |
chushengyuan | 0:2885d4453e88 | 313 | |
chushengyuan | 0:2885d4453e88 | 314 | lcd.setPixel(42+X, 26-Y); |
chushengyuan | 0:2885d4453e88 | 315 | lcd.setPixel(41+X, 26-Y); |
chushengyuan | 0:2885d4453e88 | 316 | lcd.setPixel(40+X, 26-Y); |
chushengyuan | 0:2885d4453e88 | 317 | lcd.setPixel(43+X, 25-Y); |
chushengyuan | 0:2885d4453e88 | 318 | lcd.setPixel(42+X, 25-Y); |
chushengyuan | 0:2885d4453e88 | 319 | lcd.setPixel(41+X, 25-Y); |
chushengyuan | 0:2885d4453e88 | 320 | lcd.setPixel(40+X, 25-Y); |
chushengyuan | 0:2885d4453e88 | 321 | lcd.setPixel(39+X, 25-Y); |
chushengyuan | 0:2885d4453e88 | 322 | lcd.setPixel(43+X, 24-Y); |
chushengyuan | 0:2885d4453e88 | 323 | lcd.setPixel(42+X, 24-Y); |
chushengyuan | 0:2885d4453e88 | 324 | lcd.setPixel(41+X, 24-Y); |
chushengyuan | 0:2885d4453e88 | 325 | lcd.setPixel(40+X, 24-Y); |
chushengyuan | 0:2885d4453e88 | 326 | lcd.setPixel(39+X, 24-Y); |
chushengyuan | 0:2885d4453e88 | 327 | lcd.setPixel(43+X, 23-Y); |
chushengyuan | 0:2885d4453e88 | 328 | lcd.setPixel(42+X, 23-Y); |
chushengyuan | 0:2885d4453e88 | 329 | lcd.setPixel(41+X, 23-Y); |
chushengyuan | 0:2885d4453e88 | 330 | lcd.setPixel(40+X, 23-Y); |
chushengyuan | 0:2885d4453e88 | 331 | lcd.setPixel(39+X, 23-Y); |
chushengyuan | 0:2885d4453e88 | 332 | lcd.setPixel(42+X, 22-Y); |
chushengyuan | 0:2885d4453e88 | 333 | lcd.setPixel(41+X, 22-Y); |
chushengyuan | 0:2885d4453e88 | 334 | lcd.setPixel(40+X, 22-Y); |
chushengyuan | 0:2885d4453e88 | 335 | lcd.refresh(); |
chushengyuan | 0:2885d4453e88 | 336 | |
chushengyuan | 0:2885d4453e88 | 337 | /**Displayed pixes will be cleared after 0.2 second.*/ |
chushengyuan | 0:2885d4453e88 | 338 | wait(0.2); |
chushengyuan | 0:2885d4453e88 | 339 | |
chushengyuan | 0:2885d4453e88 | 340 | lcd.clearPixel(42+X, 26-Y); |
chushengyuan | 0:2885d4453e88 | 341 | lcd.clearPixel(41+X, 26-Y); |
chushengyuan | 0:2885d4453e88 | 342 | lcd.clearPixel(40+X, 26-Y); |
chushengyuan | 0:2885d4453e88 | 343 | lcd.clearPixel(43+X, 25-Y); |
chushengyuan | 0:2885d4453e88 | 344 | lcd.clearPixel(42+X, 25-Y); |
chushengyuan | 0:2885d4453e88 | 345 | lcd.clearPixel(41+X, 25-Y); |
chushengyuan | 0:2885d4453e88 | 346 | lcd.clearPixel(40+X, 25-Y); |
chushengyuan | 0:2885d4453e88 | 347 | lcd.clearPixel(39+X, 25-Y); |
chushengyuan | 0:2885d4453e88 | 348 | lcd.clearPixel(43+X, 24-Y); |
chushengyuan | 0:2885d4453e88 | 349 | lcd.clearPixel(42+X, 24-Y); |
chushengyuan | 0:2885d4453e88 | 350 | lcd.clearPixel(41+X, 24-Y); |
chushengyuan | 0:2885d4453e88 | 351 | lcd.clearPixel(40+X, 24-Y); |
chushengyuan | 0:2885d4453e88 | 352 | lcd.clearPixel(39+X, 24-Y); |
chushengyuan | 0:2885d4453e88 | 353 | lcd.clearPixel(43+X, 23-Y); |
chushengyuan | 0:2885d4453e88 | 354 | lcd.clearPixel(42+X, 23-Y); |
chushengyuan | 0:2885d4453e88 | 355 | lcd.clearPixel(41+X, 23-Y); |
chushengyuan | 0:2885d4453e88 | 356 | lcd.clearPixel(40+X, 23-Y); |
chushengyuan | 0:2885d4453e88 | 357 | lcd.clearPixel(39+X, 23-Y); |
chushengyuan | 0:2885d4453e88 | 358 | lcd.clearPixel(42+X, 22-Y); |
chushengyuan | 0:2885d4453e88 | 359 | lcd.clearPixel(41+X, 22-Y); |
chushengyuan | 0:2885d4453e88 | 360 | lcd.clearPixel(40+X, 22-Y); |
chushengyuan | 0:2885d4453e88 | 361 | lcd.refresh(); |
chushengyuan | 0:2885d4453e88 | 362 | } |
chushengyuan | 0:2885d4453e88 | 363 | |
chushengyuan | 0:2885d4453e88 | 364 | /**All LEDs will be turned on if acceleration values are within -0.05 and 0.05.*/ |
chushengyuan | 0:2885d4453e88 | 365 | if (abs(Ax)<=0.05&&abs(Ay)<=0.05) { |
chushengyuan | 0:2885d4453e88 | 366 | ledA=1; |
chushengyuan | 0:2885d4453e88 | 367 | ledB=1; |
chushengyuan | 0:2885d4453e88 | 368 | ledC=1; |
chushengyuan | 0:2885d4453e88 | 369 | ledD=1; |
chushengyuan | 0:2885d4453e88 | 370 | } |
chushengyuan | 0:2885d4453e88 | 371 | |
chushengyuan | 0:2885d4453e88 | 372 | /**All LEDs will be turned off if acceleration values go beyond this range.*/ |
chushengyuan | 0:2885d4453e88 | 373 | else { |
chushengyuan | 0:2885d4453e88 | 374 | ledA=0; |
chushengyuan | 0:2885d4453e88 | 375 | ledB=0; |
chushengyuan | 0:2885d4453e88 | 376 | ledC=0; |
chushengyuan | 0:2885d4453e88 | 377 | ledD=0; |
chushengyuan | 0:2885d4453e88 | 378 | } |
chushengyuan | 0:2885d4453e88 | 379 | } |
chushengyuan | 0:2885d4453e88 | 380 | } |
chushengyuan | 0:2885d4453e88 | 381 | |
chushengyuan | 0:2885d4453e88 | 382 | /** |
chushengyuan | 0:2885d4453e88 | 383 | @brief Display the function name of Angle Meter for 1 second before calling it. |
chushengyuan | 0:2885d4453e88 | 384 | */ |
chushengyuan | 0:2885d4453e88 | 385 | void fun1() |
chushengyuan | 0:2885d4453e88 | 386 | { |
chushengyuan | 0:2885d4453e88 | 387 | /**Initialise the LCD and set brightness to 0.8.*/ |
chushengyuan | 0:2885d4453e88 | 388 | lcd.init(); |
chushengyuan | 0:2885d4453e88 | 389 | lcd.normalMode(); |
chushengyuan | 0:2885d4453e88 | 390 | lcd.setBrightness(0.8); |
chushengyuan | 0:2885d4453e88 | 391 | lcd.clear(); |
chushengyuan | 0:2885d4453e88 | 392 | |
chushengyuan | 0:2885d4453e88 | 393 | /**Display the function name of Angle Meter.*/ |
chushengyuan | 0:2885d4453e88 | 394 | lcd.printString("Electronic",12,2); |
chushengyuan | 0:2885d4453e88 | 395 | lcd.printString("Angle Meter",10,3); |
chushengyuan | 0:2885d4453e88 | 396 | |
chushengyuan | 0:2885d4453e88 | 397 | /**Turn LED A and LED C on.*/ |
chushengyuan | 0:2885d4453e88 | 398 | ledA=1; |
chushengyuan | 0:2885d4453e88 | 399 | ledB=0; |
chushengyuan | 0:2885d4453e88 | 400 | ledC=1; |
chushengyuan | 0:2885d4453e88 | 401 | ledD=0; |
chushengyuan | 0:2885d4453e88 | 402 | |
chushengyuan | 0:2885d4453e88 | 403 | /**Call function of Angle Meter after 1 second delay.*/ |
chushengyuan | 0:2885d4453e88 | 404 | flipper.attach(&AngleMeter, 1.0); |
chushengyuan | 0:2885d4453e88 | 405 | } |
chushengyuan | 0:2885d4453e88 | 406 | |
chushengyuan | 0:2885d4453e88 | 407 | /** |
chushengyuan | 1:f167423f6f0c | 408 | @brief Display the function name of Spirit Level for 1 second before calling it. |
chushengyuan | 0:2885d4453e88 | 409 | */ |
chushengyuan | 0:2885d4453e88 | 410 | void fun2() |
chushengyuan | 0:2885d4453e88 | 411 | { |
chushengyuan | 0:2885d4453e88 | 412 | /**Turn off the buzzer.*/ |
chushengyuan | 0:2885d4453e88 | 413 | buzzer = 0; |
chushengyuan | 0:2885d4453e88 | 414 | |
chushengyuan | 0:2885d4453e88 | 415 | /**Initialise the LCD and set brightness to 0.8.*/ |
chushengyuan | 0:2885d4453e88 | 416 | lcd.init(); |
chushengyuan | 0:2885d4453e88 | 417 | lcd.normalMode(); |
chushengyuan | 0:2885d4453e88 | 418 | lcd.setBrightness(0.8); |
chushengyuan | 0:2885d4453e88 | 419 | lcd.clear(); |
chushengyuan | 0:2885d4453e88 | 420 | |
chushengyuan | 1:f167423f6f0c | 421 | /**Display the function name of Spirit Level.*/ |
chushengyuan | 0:2885d4453e88 | 422 | lcd.printString("Electronic",12,2); |
chushengyuan | 1:f167423f6f0c | 423 | lcd.printString("Spirit Level",7,3); |
chushengyuan | 0:2885d4453e88 | 424 | |
chushengyuan | 0:2885d4453e88 | 425 | /**Turn LED B and LED D on.*/ |
chushengyuan | 0:2885d4453e88 | 426 | ledA=0; |
chushengyuan | 0:2885d4453e88 | 427 | ledB=1; |
chushengyuan | 0:2885d4453e88 | 428 | ledC=0; |
chushengyuan | 0:2885d4453e88 | 429 | ledD=1; |
chushengyuan | 0:2885d4453e88 | 430 | |
chushengyuan | 1:f167423f6f0c | 431 | /**Call function of Spirit Level after 1 second delay.*/ |
chushengyuan | 1:f167423f6f0c | 432 | flipper.attach(&SpiritLevel, 1.0); |
chushengyuan | 0:2885d4453e88 | 433 | } |
chushengyuan | 0:2885d4453e88 | 434 | |
chushengyuan | 0:2885d4453e88 | 435 | /** |
chushengyuan | 0:2885d4453e88 | 436 | @brief Power down the Ethernet interface to save power. |
chushengyuan | 0:2885d4453e88 | 437 | @brief Acknowledgements to Michael Wei's code. |
chushengyuan | 0:2885d4453e88 | 438 | */ |
chushengyuan | 0:2885d4453e88 | 439 | void PHY_PowerDown() |
chushengyuan | 0:2885d4453e88 | 440 | { |
chushengyuan | 0:2885d4453e88 | 441 | if (!Peripheral_GetStatus(LPC1768_PCONP_PCENET)) |
chushengyuan | 0:2885d4453e88 | 442 | EMAC_Init(); //init EMAC if it is not already init'd |
chushengyuan | 0:2885d4453e88 | 443 | |
chushengyuan | 0:2885d4453e88 | 444 | unsigned int regv; |
chushengyuan | 0:2885d4453e88 | 445 | regv = read_PHY(PHY_REG_BMCR); |
chushengyuan | 0:2885d4453e88 | 446 | write_PHY(PHY_REG_BMCR, regv | (1 << PHY_REG_BMCR_POWERDOWN)); |
chushengyuan | 0:2885d4453e88 | 447 | regv = read_PHY(PHY_REG_BMCR); |
chushengyuan | 0:2885d4453e88 | 448 | |
chushengyuan | 0:2885d4453e88 | 449 | //shouldn't need the EMAC now. |
chushengyuan | 0:2885d4453e88 | 450 | Peripheral_PowerDown(LPC1768_PCONP_PCENET); |
chushengyuan | 0:2885d4453e88 | 451 | |
chushengyuan | 0:2885d4453e88 | 452 | //and turn off the PHY OSC |
chushengyuan | 0:2885d4453e88 | 453 | LPC_GPIO1->FIODIR |= 0x8000000; |
chushengyuan | 0:2885d4453e88 | 454 | LPC_GPIO1->FIOCLR = 0x8000000; |
chushengyuan | 0:2885d4453e88 | 455 | } |
chushengyuan | 0:2885d4453e88 | 456 | |
chushengyuan | 0:2885d4453e88 | 457 | static void write_PHY (unsigned int PhyReg, unsigned short Value) { |
chushengyuan | 0:2885d4453e88 | 458 | /* Write a data 'Value' to PHY register 'PhyReg'. */ |
chushengyuan | 0:2885d4453e88 | 459 | unsigned int tout; |
chushengyuan | 0:2885d4453e88 | 460 | /* Hardware MII Management for LPC176x devices. */ |
chushengyuan | 0:2885d4453e88 | 461 | LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg; |
chushengyuan | 0:2885d4453e88 | 462 | LPC_EMAC->MWTD = Value; |
chushengyuan | 0:2885d4453e88 | 463 | |
chushengyuan | 0:2885d4453e88 | 464 | /* Wait utill operation completed */ |
chushengyuan | 0:2885d4453e88 | 465 | for (tout = 0; tout < MII_WR_TOUT; tout++) { |
chushengyuan | 0:2885d4453e88 | 466 | if ((LPC_EMAC->MIND & MIND_BUSY) == 0) { |
chushengyuan | 0:2885d4453e88 | 467 | break; |
chushengyuan | 0:2885d4453e88 | 468 | } |
chushengyuan | 0:2885d4453e88 | 469 | } |
chushengyuan | 0:2885d4453e88 | 470 | } |
chushengyuan | 0:2885d4453e88 | 471 | |
chushengyuan | 0:2885d4453e88 | 472 | static unsigned short read_PHY (unsigned int PhyReg) { |
chushengyuan | 0:2885d4453e88 | 473 | /* Read a PHY register 'PhyReg'. */ |
chushengyuan | 0:2885d4453e88 | 474 | unsigned int tout, val; |
chushengyuan | 0:2885d4453e88 | 475 | |
chushengyuan | 0:2885d4453e88 | 476 | LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg; |
chushengyuan | 0:2885d4453e88 | 477 | LPC_EMAC->MCMD = MCMD_READ; |
chushengyuan | 0:2885d4453e88 | 478 | |
chushengyuan | 0:2885d4453e88 | 479 | /* Wait until operation completed */ |
chushengyuan | 0:2885d4453e88 | 480 | for (tout = 0; tout < MII_RD_TOUT; tout++) { |
chushengyuan | 0:2885d4453e88 | 481 | if ((LPC_EMAC->MIND & MIND_BUSY) == 0) { |
chushengyuan | 0:2885d4453e88 | 482 | break; |
chushengyuan | 0:2885d4453e88 | 483 | } |
chushengyuan | 0:2885d4453e88 | 484 | } |
chushengyuan | 0:2885d4453e88 | 485 | LPC_EMAC->MCMD = 0; |
chushengyuan | 0:2885d4453e88 | 486 | val = LPC_EMAC->MRDD; |
chushengyuan | 0:2885d4453e88 | 487 | |
chushengyuan | 0:2885d4453e88 | 488 | return (val); |
chushengyuan | 0:2885d4453e88 | 489 | } |
chushengyuan | 0:2885d4453e88 | 490 | |
chushengyuan | 0:2885d4453e88 | 491 | void EMAC_Init() |
chushengyuan | 0:2885d4453e88 | 492 | { |
chushengyuan | 0:2885d4453e88 | 493 | unsigned int tout,regv; |
chushengyuan | 0:2885d4453e88 | 494 | /* Power Up the EMAC controller. */ |
chushengyuan | 0:2885d4453e88 | 495 | Peripheral_PowerUp(LPC1768_PCONP_PCENET); |
chushengyuan | 0:2885d4453e88 | 496 | |
chushengyuan | 0:2885d4453e88 | 497 | LPC_PINCON->PINSEL2 = 0x50150105; |
chushengyuan | 0:2885d4453e88 | 498 | LPC_PINCON->PINSEL3 &= ~0x0000000F; |
chushengyuan | 0:2885d4453e88 | 499 | LPC_PINCON->PINSEL3 |= 0x00000005; |
chushengyuan | 0:2885d4453e88 | 500 | |
chushengyuan | 0:2885d4453e88 | 501 | /* Reset all EMAC internal modules. */ |
chushengyuan | 0:2885d4453e88 | 502 | LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | |
chushengyuan | 0:2885d4453e88 | 503 | MAC1_SIM_RES | MAC1_SOFT_RES; |
chushengyuan | 0:2885d4453e88 | 504 | LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES; |
chushengyuan | 0:2885d4453e88 | 505 | |
chushengyuan | 0:2885d4453e88 | 506 | /* A short delay after reset. */ |
chushengyuan | 0:2885d4453e88 | 507 | for (tout = 100; tout; tout--); |
chushengyuan | 0:2885d4453e88 | 508 | |
chushengyuan | 0:2885d4453e88 | 509 | /* Initialize MAC control registers. */ |
chushengyuan | 0:2885d4453e88 | 510 | LPC_EMAC->MAC1 = MAC1_PASS_ALL; |
chushengyuan | 0:2885d4453e88 | 511 | LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN; |
chushengyuan | 0:2885d4453e88 | 512 | LPC_EMAC->MAXF = ETH_MAX_FLEN; |
chushengyuan | 0:2885d4453e88 | 513 | LPC_EMAC->CLRT = CLRT_DEF; |
chushengyuan | 0:2885d4453e88 | 514 | LPC_EMAC->IPGR = IPGR_DEF; |
chushengyuan | 0:2885d4453e88 | 515 | |
chushengyuan | 0:2885d4453e88 | 516 | /* Enable Reduced MII interface. */ |
chushengyuan | 0:2885d4453e88 | 517 | LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM; |
chushengyuan | 0:2885d4453e88 | 518 | |
chushengyuan | 0:2885d4453e88 | 519 | /* Reset Reduced MII Logic. */ |
chushengyuan | 0:2885d4453e88 | 520 | LPC_EMAC->SUPP = SUPP_RES_RMII; |
chushengyuan | 0:2885d4453e88 | 521 | for (tout = 100; tout; tout--); |
chushengyuan | 0:2885d4453e88 | 522 | LPC_EMAC->SUPP = 0; |
chushengyuan | 0:2885d4453e88 | 523 | |
chushengyuan | 0:2885d4453e88 | 524 | /* Put the DP83848C in reset mode */ |
chushengyuan | 0:2885d4453e88 | 525 | write_PHY (PHY_REG_BMCR, 0x8000); |
chushengyuan | 0:2885d4453e88 | 526 | |
chushengyuan | 0:2885d4453e88 | 527 | /* Wait for hardware reset to end. */ |
chushengyuan | 0:2885d4453e88 | 528 | for (tout = 0; tout < 0x100000; tout++) { |
chushengyuan | 0:2885d4453e88 | 529 | regv = read_PHY (PHY_REG_BMCR); |
chushengyuan | 0:2885d4453e88 | 530 | if (!(regv & 0x8000)) { |
chushengyuan | 0:2885d4453e88 | 531 | /* Reset complete */ |
chushengyuan | 0:2885d4453e88 | 532 | break; |
chushengyuan | 0:2885d4453e88 | 533 | } |
chushengyuan | 0:2885d4453e88 | 534 | } |
chushengyuan | 0:2885d4453e88 | 535 | } |
chushengyuan | 0:2885d4453e88 | 536 | |
chushengyuan | 0:2885d4453e88 | 537 | /** |
chushengyuan | 0:2885d4453e88 | 538 | @brief Functions used to display characters and shapes. |
chushengyuan | 0:2885d4453e88 | 539 | @brief Acknowledgements to Dr.Craig A. Evans's code. |
chushengyuan | 0:2885d4453e88 | 540 | */ |
chushengyuan | 0:2885d4453e88 | 541 | N5110::N5110(PinName pwrPin, PinName scePin, PinName rstPin, PinName dcPin, PinName mosiPin, PinName sclkPin, PinName ledPin) |
chushengyuan | 0:2885d4453e88 | 542 | { |
chushengyuan | 0:2885d4453e88 | 543 | |
chushengyuan | 0:2885d4453e88 | 544 | spi = new SPI(mosiPin,NC,sclkPin); // create new SPI instance and initialise |
chushengyuan | 0:2885d4453e88 | 545 | initSPI(); |
chushengyuan | 0:2885d4453e88 | 546 | |
chushengyuan | 0:2885d4453e88 | 547 | // set up pins as required |
chushengyuan | 0:2885d4453e88 | 548 | led = new PwmOut(ledPin); |
chushengyuan | 0:2885d4453e88 | 549 | pwr = new DigitalOut(pwrPin); |
chushengyuan | 0:2885d4453e88 | 550 | sce = new DigitalOut(scePin); |
chushengyuan | 0:2885d4453e88 | 551 | rst = new DigitalOut(rstPin); |
chushengyuan | 0:2885d4453e88 | 552 | dc = new DigitalOut(dcPin); |
chushengyuan | 0:2885d4453e88 | 553 | |
chushengyuan | 0:2885d4453e88 | 554 | } |
chushengyuan | 0:2885d4453e88 | 555 | |
chushengyuan | 0:2885d4453e88 | 556 | // initialise function - powers up and sends the initialisation commands |
chushengyuan | 0:2885d4453e88 | 557 | void N5110::init() |
chushengyuan | 0:2885d4453e88 | 558 | { |
chushengyuan | 0:2885d4453e88 | 559 | turnOn(); // power up |
chushengyuan | 0:2885d4453e88 | 560 | wait_ms(10); // small delay seems to prevent spurious pixels during mbed reset |
chushengyuan | 0:2885d4453e88 | 561 | reset(); // reset LCD - must be done within 100 ms |
chushengyuan | 0:2885d4453e88 | 562 | |
chushengyuan | 0:2885d4453e88 | 563 | // function set - extended |
chushengyuan | 0:2885d4453e88 | 564 | sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_EXTENDED_MODE); |
chushengyuan | 0:2885d4453e88 | 565 | // Don't completely understand these parameters - they seem to work as they are |
chushengyuan | 0:2885d4453e88 | 566 | // Consult the datasheet if you need to change them |
chushengyuan | 0:2885d4453e88 | 567 | sendCommand(CMD_VOP_7V38); // operating voltage - these values are from Chris Yan's Library |
chushengyuan | 0:2885d4453e88 | 568 | sendCommand(CMD_TC_TEMP_2); // temperature control |
chushengyuan | 0:2885d4453e88 | 569 | sendCommand(CMD_BI_MUX_48); // bias |
chushengyuan | 0:2885d4453e88 | 570 | |
chushengyuan | 0:2885d4453e88 | 571 | // function set - basic |
chushengyuan | 0:2885d4453e88 | 572 | sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_BASIC_MODE); |
chushengyuan | 0:2885d4453e88 | 573 | normalMode(); // normal video mode by default |
chushengyuan | 0:2885d4453e88 | 574 | sendCommand(CMD_DC_NORMAL_MODE); // black on white |
chushengyuan | 0:2885d4453e88 | 575 | |
chushengyuan | 0:2885d4453e88 | 576 | // RAM is undefined at power-up so clear |
chushengyuan | 0:2885d4453e88 | 577 | clearRAM(); |
chushengyuan | 0:2885d4453e88 | 578 | |
chushengyuan | 0:2885d4453e88 | 579 | } |
chushengyuan | 0:2885d4453e88 | 580 | |
chushengyuan | 0:2885d4453e88 | 581 | // sets normal video mode (black on white) |
chushengyuan | 0:2885d4453e88 | 582 | void N5110::normalMode() |
chushengyuan | 0:2885d4453e88 | 583 | { |
chushengyuan | 0:2885d4453e88 | 584 | sendCommand(CMD_DC_NORMAL_MODE); |
chushengyuan | 0:2885d4453e88 | 585 | |
chushengyuan | 0:2885d4453e88 | 586 | } |
chushengyuan | 0:2885d4453e88 | 587 | |
chushengyuan | 0:2885d4453e88 | 588 | // sets normal video mode (white on black) |
chushengyuan | 0:2885d4453e88 | 589 | void N5110::inverseMode() |
chushengyuan | 0:2885d4453e88 | 590 | { |
chushengyuan | 0:2885d4453e88 | 591 | sendCommand(CMD_DC_INVERT_VIDEO); |
chushengyuan | 0:2885d4453e88 | 592 | } |
chushengyuan | 0:2885d4453e88 | 593 | |
chushengyuan | 0:2885d4453e88 | 594 | // function to power up the LCD and backlight |
chushengyuan | 0:2885d4453e88 | 595 | void N5110::turnOn() |
chushengyuan | 0:2885d4453e88 | 596 | { |
chushengyuan | 0:2885d4453e88 | 597 | // set brightness of LED - 0.0 to 1.0 - default is 50% |
chushengyuan | 0:2885d4453e88 | 598 | setBrightness(0.5); |
chushengyuan | 0:2885d4453e88 | 599 | pwr->write(1); // apply power |
chushengyuan | 0:2885d4453e88 | 600 | } |
chushengyuan | 0:2885d4453e88 | 601 | |
chushengyuan | 0:2885d4453e88 | 602 | // function to power down LCD |
chushengyuan | 0:2885d4453e88 | 603 | void N5110::turnOff() |
chushengyuan | 0:2885d4453e88 | 604 | { |
chushengyuan | 0:2885d4453e88 | 605 | setBrightness(0.0); // turn backlight off |
chushengyuan | 0:2885d4453e88 | 606 | clearRAM(); // clear RAM to ensure specified current consumption |
chushengyuan | 0:2885d4453e88 | 607 | // send command to ensure we are in basic mode |
chushengyuan | 0:2885d4453e88 | 608 | sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_BASIC_MODE); |
chushengyuan | 0:2885d4453e88 | 609 | // clear the display |
chushengyuan | 0:2885d4453e88 | 610 | sendCommand(CMD_DC_CLEAR_DISPLAY); |
chushengyuan | 0:2885d4453e88 | 611 | // enter the extended mode and power down |
chushengyuan | 0:2885d4453e88 | 612 | sendCommand(0x20 | CMD_FS_POWER_DOWN_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_EXTENDED_MODE); |
chushengyuan | 0:2885d4453e88 | 613 | // small delay and then turn off the power pin |
chushengyuan | 0:2885d4453e88 | 614 | wait_ms(10); |
chushengyuan | 0:2885d4453e88 | 615 | pwr->write(0); |
chushengyuan | 0:2885d4453e88 | 616 | |
chushengyuan | 0:2885d4453e88 | 617 | } |
chushengyuan | 0:2885d4453e88 | 618 | |
chushengyuan | 0:2885d4453e88 | 619 | // function to change LED backlight brightness |
chushengyuan | 0:2885d4453e88 | 620 | void N5110::setBrightness(float brightness) |
chushengyuan | 0:2885d4453e88 | 621 | { |
chushengyuan | 0:2885d4453e88 | 622 | // check whether brightness is within range |
chushengyuan | 0:2885d4453e88 | 623 | if (brightness < 0.0) |
chushengyuan | 0:2885d4453e88 | 624 | brightness = 0.0; |
chushengyuan | 0:2885d4453e88 | 625 | if (brightness > 1.0) |
chushengyuan | 0:2885d4453e88 | 626 | brightness = 1.0; |
chushengyuan | 0:2885d4453e88 | 627 | // set PWM duty cycle |
chushengyuan | 0:2885d4453e88 | 628 | led->write(brightness); |
chushengyuan | 0:2885d4453e88 | 629 | } |
chushengyuan | 0:2885d4453e88 | 630 | |
chushengyuan | 0:2885d4453e88 | 631 | // pulse the active low reset line |
chushengyuan | 0:2885d4453e88 | 632 | void N5110::reset() |
chushengyuan | 0:2885d4453e88 | 633 | { |
chushengyuan | 0:2885d4453e88 | 634 | rst->write(0); // reset the LCD |
chushengyuan | 0:2885d4453e88 | 635 | rst->write(1); |
chushengyuan | 0:2885d4453e88 | 636 | } |
chushengyuan | 0:2885d4453e88 | 637 | |
chushengyuan | 0:2885d4453e88 | 638 | // function to initialise SPI peripheral |
chushengyuan | 0:2885d4453e88 | 639 | void N5110::initSPI() |
chushengyuan | 0:2885d4453e88 | 640 | { |
chushengyuan | 0:2885d4453e88 | 641 | spi->format(8,1); // 8 bits, Mode 1 - polarity 0, phase 1 - base value of clock is 0, data captured on falling edge/propagated on rising edge |
chushengyuan | 0:2885d4453e88 | 642 | spi->frequency(4000000); // maximum of screen is 4 MHz |
chushengyuan | 0:2885d4453e88 | 643 | } |
chushengyuan | 0:2885d4453e88 | 644 | |
chushengyuan | 0:2885d4453e88 | 645 | // send a command to the display |
chushengyuan | 0:2885d4453e88 | 646 | void N5110::sendCommand(unsigned char command) |
chushengyuan | 0:2885d4453e88 | 647 | { |
chushengyuan | 0:2885d4453e88 | 648 | dc->write(0); // set DC low for command |
chushengyuan | 0:2885d4453e88 | 649 | sce->write(0); // set CE low to begin frame |
chushengyuan | 0:2885d4453e88 | 650 | spi->write(command); // send command |
chushengyuan | 0:2885d4453e88 | 651 | dc->write(1); // turn back to data by default |
chushengyuan | 0:2885d4453e88 | 652 | sce->write(1); // set CE high to end frame (expected for transmission of single byte) |
chushengyuan | 0:2885d4453e88 | 653 | |
chushengyuan | 0:2885d4453e88 | 654 | } |
chushengyuan | 0:2885d4453e88 | 655 | |
chushengyuan | 0:2885d4453e88 | 656 | // this function writes 0 to the 504 bytes to clear the RAM |
chushengyuan | 0:2885d4453e88 | 657 | void N5110::clearRAM() |
chushengyuan | 0:2885d4453e88 | 658 | { |
chushengyuan | 0:2885d4453e88 | 659 | int i; |
chushengyuan | 0:2885d4453e88 | 660 | sce->write(0); //set CE low to begin frame |
chushengyuan | 0:2885d4453e88 | 661 | for(i = 0; i < WIDTH * HEIGHT; i++) { // 48 x 84 bits = 504 bytes |
chushengyuan | 0:2885d4453e88 | 662 | spi->write(0x00); // send 0's |
chushengyuan | 0:2885d4453e88 | 663 | } |
chushengyuan | 0:2885d4453e88 | 664 | sce->write(1); // set CE high to end frame |
chushengyuan | 0:2885d4453e88 | 665 | |
chushengyuan | 0:2885d4453e88 | 666 | } |
chushengyuan | 0:2885d4453e88 | 667 | |
chushengyuan | 0:2885d4453e88 | 668 | // function to set the XY address in RAM for subsequenct data write |
chushengyuan | 0:2885d4453e88 | 669 | void N5110::setXYAddress(int x, int y) |
chushengyuan | 0:2885d4453e88 | 670 | { |
chushengyuan | 0:2885d4453e88 | 671 | if (x>=0 && x<WIDTH && y>=0 && y<HEIGHT) { // check within range |
chushengyuan | 0:2885d4453e88 | 672 | sendCommand(0x80 | x); // send addresses to display with relevant mask |
chushengyuan | 0:2885d4453e88 | 673 | sendCommand(0x40 | y); |
chushengyuan | 0:2885d4453e88 | 674 | } |
chushengyuan | 0:2885d4453e88 | 675 | } |
chushengyuan | 0:2885d4453e88 | 676 | |
chushengyuan | 0:2885d4453e88 | 677 | // These functions are used to set, clear and get the value of pixels in the display |
chushengyuan | 0:2885d4453e88 | 678 | // Pixels are addressed in the range of 0 to 47 (y) and 0 to 83 (x). The refresh() |
chushengyuan | 0:2885d4453e88 | 679 | // function must be called after set and clear in order to update the display |
chushengyuan | 0:2885d4453e88 | 680 | void N5110::setPixel(int x, int y) |
chushengyuan | 0:2885d4453e88 | 681 | { |
chushengyuan | 0:2885d4453e88 | 682 | if (x>=0 && x<WIDTH && y>=0 && y<HEIGHT) { // check within range |
chushengyuan | 0:2885d4453e88 | 683 | // calculate bank and shift 1 to required position in the data byte |
chushengyuan | 0:2885d4453e88 | 684 | buffer[x][y/8] |= (1 << y%8); |
chushengyuan | 0:2885d4453e88 | 685 | } |
chushengyuan | 0:2885d4453e88 | 686 | } |
chushengyuan | 0:2885d4453e88 | 687 | |
chushengyuan | 0:2885d4453e88 | 688 | void N5110::clearPixel(int x, int y) |
chushengyuan | 0:2885d4453e88 | 689 | { |
chushengyuan | 0:2885d4453e88 | 690 | if (x>=0 && x<WIDTH && y>=0 && y<HEIGHT) { // check within range |
chushengyuan | 0:2885d4453e88 | 691 | // calculate bank and shift 1 to required position (using bit clear) |
chushengyuan | 0:2885d4453e88 | 692 | buffer[x][y/8] &= ~(1 << y%8); |
chushengyuan | 0:2885d4453e88 | 693 | } |
chushengyuan | 0:2885d4453e88 | 694 | } |
chushengyuan | 0:2885d4453e88 | 695 | |
chushengyuan | 0:2885d4453e88 | 696 | // function to refresh the display |
chushengyuan | 0:2885d4453e88 | 697 | void N5110::refresh() |
chushengyuan | 0:2885d4453e88 | 698 | { |
chushengyuan | 0:2885d4453e88 | 699 | int i,j; |
chushengyuan | 0:2885d4453e88 | 700 | |
chushengyuan | 0:2885d4453e88 | 701 | setXYAddress(0,0); // important to set address back to 0,0 before refreshing display |
chushengyuan | 0:2885d4453e88 | 702 | // address auto increments after printing string, so buffer[0][0] will not coincide |
chushengyuan | 0:2885d4453e88 | 703 | // with top-left pixel after priting string |
chushengyuan | 0:2885d4453e88 | 704 | |
chushengyuan | 0:2885d4453e88 | 705 | sce->write(0); //set CE low to begin frame |
chushengyuan | 0:2885d4453e88 | 706 | |
chushengyuan | 0:2885d4453e88 | 707 | for(j = 0; j < BANKS; j++) { // be careful to use correct order (j,i) for horizontal addressing |
chushengyuan | 0:2885d4453e88 | 708 | for(i = 0; i < WIDTH; i++) { |
chushengyuan | 0:2885d4453e88 | 709 | spi->write(buffer[i][j]); // send buffer |
chushengyuan | 0:2885d4453e88 | 710 | } |
chushengyuan | 0:2885d4453e88 | 711 | } |
chushengyuan | 0:2885d4453e88 | 712 | sce->write(1); // set CE high to end frame |
chushengyuan | 0:2885d4453e88 | 713 | |
chushengyuan | 0:2885d4453e88 | 714 | } |
chushengyuan | 0:2885d4453e88 | 715 | |
chushengyuan | 0:2885d4453e88 | 716 | // function to print string at specified position |
chushengyuan | 0:2885d4453e88 | 717 | void N5110::printString(const char * str,int x,int y) |
chushengyuan | 0:2885d4453e88 | 718 | { |
chushengyuan | 0:2885d4453e88 | 719 | if (y>=0 && y<BANKS) { // check if printing in range of y banks |
chushengyuan | 0:2885d4453e88 | 720 | |
chushengyuan | 0:2885d4453e88 | 721 | int n = 0 ; // counter for number of characters in string |
chushengyuan | 0:2885d4453e88 | 722 | // loop through string and print character |
chushengyuan | 0:2885d4453e88 | 723 | while(*str) { |
chushengyuan | 0:2885d4453e88 | 724 | |
chushengyuan | 0:2885d4453e88 | 725 | // writes the character bitmap data to the buffer, so that |
chushengyuan | 0:2885d4453e88 | 726 | // text and pixels can be displayed at the same time |
chushengyuan | 0:2885d4453e88 | 727 | for (int i = 0; i < 5 ; i++ ) { |
chushengyuan | 0:2885d4453e88 | 728 | int pixel_x = x+i+n*6; |
chushengyuan | 0:2885d4453e88 | 729 | if (pixel_x > WIDTH-1) // ensure pixel isn't outside the buffer size (0 - 83) |
chushengyuan | 0:2885d4453e88 | 730 | break; |
chushengyuan | 0:2885d4453e88 | 731 | buffer[pixel_x][y] = font5x7[(*str - 32)*5 + i]; |
chushengyuan | 0:2885d4453e88 | 732 | } |
chushengyuan | 0:2885d4453e88 | 733 | |
chushengyuan | 0:2885d4453e88 | 734 | str++; // go to next character in string |
chushengyuan | 0:2885d4453e88 | 735 | |
chushengyuan | 0:2885d4453e88 | 736 | n++; // increment index |
chushengyuan | 0:2885d4453e88 | 737 | |
chushengyuan | 0:2885d4453e88 | 738 | } |
chushengyuan | 0:2885d4453e88 | 739 | |
chushengyuan | 0:2885d4453e88 | 740 | refresh(); // this sends the buffer to the display and sets address (cursor) back to 0,0 |
chushengyuan | 0:2885d4453e88 | 741 | } |
chushengyuan | 0:2885d4453e88 | 742 | } |
chushengyuan | 0:2885d4453e88 | 743 | |
chushengyuan | 0:2885d4453e88 | 744 | // function to clear the screen |
chushengyuan | 0:2885d4453e88 | 745 | void N5110::clear() |
chushengyuan | 0:2885d4453e88 | 746 | { |
chushengyuan | 0:2885d4453e88 | 747 | clearBuffer(); // clear the buffer then call the refresh function |
chushengyuan | 0:2885d4453e88 | 748 | refresh(); |
chushengyuan | 0:2885d4453e88 | 749 | } |
chushengyuan | 0:2885d4453e88 | 750 | |
chushengyuan | 0:2885d4453e88 | 751 | // function to clear the buffer |
chushengyuan | 0:2885d4453e88 | 752 | void N5110::clearBuffer() |
chushengyuan | 0:2885d4453e88 | 753 | { |
chushengyuan | 0:2885d4453e88 | 754 | int i,j; |
chushengyuan | 0:2885d4453e88 | 755 | for (i=0; i<WIDTH; i++) { // loop through the banks and set the buffer to 0 |
chushengyuan | 0:2885d4453e88 | 756 | for (j=0; j<BANKS; j++) { |
chushengyuan | 0:2885d4453e88 | 757 | buffer[i][j]=0; |
chushengyuan | 0:2885d4453e88 | 758 | } |
chushengyuan | 0:2885d4453e88 | 759 | } |
chushengyuan | 0:2885d4453e88 | 760 | } |
chushengyuan | 0:2885d4453e88 | 761 | |
chushengyuan | 0:2885d4453e88 | 762 | // function to draw circle |
chushengyuan | 0:2885d4453e88 | 763 | void N5110:: drawCircle(int x0,int y0,int radius,int fill) |
chushengyuan | 0:2885d4453e88 | 764 | { |
chushengyuan | 0:2885d4453e88 | 765 | // from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm |
chushengyuan | 0:2885d4453e88 | 766 | int x = radius; |
chushengyuan | 0:2885d4453e88 | 767 | int y = 0; |
chushengyuan | 0:2885d4453e88 | 768 | int radiusError = 1-x; |
chushengyuan | 0:2885d4453e88 | 769 | |
chushengyuan | 0:2885d4453e88 | 770 | while(x >= y) { |
chushengyuan | 0:2885d4453e88 | 771 | |
chushengyuan | 0:2885d4453e88 | 772 | // if transparent, just draw outline |
chushengyuan | 0:2885d4453e88 | 773 | if (fill == 0) { |
chushengyuan | 0:2885d4453e88 | 774 | setPixel( x + x0, y + y0); |
chushengyuan | 0:2885d4453e88 | 775 | setPixel(-x + x0, y + y0); |
chushengyuan | 0:2885d4453e88 | 776 | setPixel( y + x0, x + y0); |
chushengyuan | 0:2885d4453e88 | 777 | setPixel(-y + x0, x + y0); |
chushengyuan | 0:2885d4453e88 | 778 | setPixel(-y + x0, -x + y0); |
chushengyuan | 0:2885d4453e88 | 779 | setPixel( y + x0, -x + y0); |
chushengyuan | 0:2885d4453e88 | 780 | setPixel( x + x0, -y + y0); |
chushengyuan | 0:2885d4453e88 | 781 | setPixel(-x + x0, -y + y0); |
chushengyuan | 0:2885d4453e88 | 782 | } else { // drawing filled circle, so draw lines between points at same y value |
chushengyuan | 0:2885d4453e88 | 783 | |
chushengyuan | 0:2885d4453e88 | 784 | int type = (fill==1) ? 1:0; // black or white fill |
chushengyuan | 0:2885d4453e88 | 785 | |
chushengyuan | 0:2885d4453e88 | 786 | drawLine(x+x0,y+y0,-x+x0,y+y0,type); |
chushengyuan | 0:2885d4453e88 | 787 | drawLine(y+x0,x+y0,-y+x0,x+y0,type); |
chushengyuan | 0:2885d4453e88 | 788 | drawLine(y+x0,-x+y0,-y+x0,-x+y0,type); |
chushengyuan | 0:2885d4453e88 | 789 | drawLine(x+x0,-y+y0,-x+x0,-y+y0,type); |
chushengyuan | 0:2885d4453e88 | 790 | } |
chushengyuan | 0:2885d4453e88 | 791 | |
chushengyuan | 0:2885d4453e88 | 792 | |
chushengyuan | 0:2885d4453e88 | 793 | y++; |
chushengyuan | 0:2885d4453e88 | 794 | if (radiusError<0) { |
chushengyuan | 0:2885d4453e88 | 795 | radiusError += 2 * y + 1; |
chushengyuan | 0:2885d4453e88 | 796 | } else { |
chushengyuan | 0:2885d4453e88 | 797 | x--; |
chushengyuan | 0:2885d4453e88 | 798 | radiusError += 2 * (y - x) + 1; |
chushengyuan | 0:2885d4453e88 | 799 | } |
chushengyuan | 0:2885d4453e88 | 800 | } |
chushengyuan | 0:2885d4453e88 | 801 | |
chushengyuan | 0:2885d4453e88 | 802 | } |
chushengyuan | 0:2885d4453e88 | 803 | |
chushengyuan | 0:2885d4453e88 | 804 | void N5110::drawLine(int x0,int y0,int x1,int y1,int type) |
chushengyuan | 0:2885d4453e88 | 805 | { |
chushengyuan | 0:2885d4453e88 | 806 | int y_range = y1-y0; // calc range of y and x |
chushengyuan | 0:2885d4453e88 | 807 | int x_range = x1-x0; |
chushengyuan | 0:2885d4453e88 | 808 | int start,stop,step; |
chushengyuan | 0:2885d4453e88 | 809 | |
chushengyuan | 0:2885d4453e88 | 810 | // if dotted line, set step to 2, else step is 1 |
chushengyuan | 0:2885d4453e88 | 811 | step = (type==2) ? 2:1; |
chushengyuan | 0:2885d4453e88 | 812 | |
chushengyuan | 0:2885d4453e88 | 813 | // make sure we loop over the largest range to get the most pixels on the display |
chushengyuan | 0:2885d4453e88 | 814 | // for instance, if drawing a vertical line (x_range = 0), we need to loop down the y pixels |
chushengyuan | 0:2885d4453e88 | 815 | // or else we'll only end up with 1 pixel in the x column |
chushengyuan | 0:2885d4453e88 | 816 | if ( abs(x_range) > abs(y_range) ) { |
chushengyuan | 0:2885d4453e88 | 817 | |
chushengyuan | 0:2885d4453e88 | 818 | // ensure we loop from smallest to largest or else for-loop won't run as expected |
chushengyuan | 0:2885d4453e88 | 819 | start = x1>x0 ? x0:x1; |
chushengyuan | 0:2885d4453e88 | 820 | stop = x1>x0 ? x1:x0; |
chushengyuan | 0:2885d4453e88 | 821 | |
chushengyuan | 0:2885d4453e88 | 822 | // loop between x pixels |
chushengyuan | 0:2885d4453e88 | 823 | for (int x = start; x<= stop ; x+=step) { |
chushengyuan | 0:2885d4453e88 | 824 | // do linear interpolation |
chushengyuan | 0:2885d4453e88 | 825 | int y = y0 + (y1-y0)*(x-x0)/(x1-x0); |
chushengyuan | 0:2885d4453e88 | 826 | |
chushengyuan | 0:2885d4453e88 | 827 | if (type == 0) // if 'white' line, turn off pixel |
chushengyuan | 0:2885d4453e88 | 828 | clearPixel(x,y); |
chushengyuan | 0:2885d4453e88 | 829 | else |
chushengyuan | 0:2885d4453e88 | 830 | setPixel(x,y); // else if 'black' or 'dotted' turn on pixel |
chushengyuan | 0:2885d4453e88 | 831 | } |
chushengyuan | 0:2885d4453e88 | 832 | } else { |
chushengyuan | 0:2885d4453e88 | 833 | |
chushengyuan | 0:2885d4453e88 | 834 | // ensure we loop from smallest to largest or else for-loop won't run as expected |
chushengyuan | 0:2885d4453e88 | 835 | start = y1>y0 ? y0:y1; |
chushengyuan | 0:2885d4453e88 | 836 | stop = y1>y0 ? y1:y0; |
chushengyuan | 0:2885d4453e88 | 837 | |
chushengyuan | 0:2885d4453e88 | 838 | for (int y = start; y<= stop ; y+=step) { |
chushengyuan | 0:2885d4453e88 | 839 | // do linear interpolation |
chushengyuan | 0:2885d4453e88 | 840 | int x = x0 + (x1-x0)*(y-y0)/(y1-y0); |
chushengyuan | 0:2885d4453e88 | 841 | |
chushengyuan | 0:2885d4453e88 | 842 | if (type == 0) // if 'white' line, turn off pixel |
chushengyuan | 0:2885d4453e88 | 843 | clearPixel(x,y); |
chushengyuan | 0:2885d4453e88 | 844 | else |
chushengyuan | 0:2885d4453e88 | 845 | setPixel(x,y); // else if 'black' or 'dotted' turn on pixel |
chushengyuan | 0:2885d4453e88 | 846 | |
chushengyuan | 0:2885d4453e88 | 847 | } |
chushengyuan | 0:2885d4453e88 | 848 | } |
chushengyuan | 0:2885d4453e88 | 849 | |
chushengyuan | 0:2885d4453e88 | 850 | } |
chushengyuan | 0:2885d4453e88 | 851 | |
chushengyuan | 0:2885d4453e88 | 852 | MMA8452:: MMA8452(PinName sdaPin, PinName sclPin) |
chushengyuan | 0:2885d4453e88 | 853 | { |
chushengyuan | 0:2885d4453e88 | 854 | i2c = new I2C(sdaPin,sclPin); // create new I2C instance and initialise |
chushengyuan | 0:2885d4453e88 | 855 | i2c->frequency(400000); // I2C Fast Mode - 400kHz |
chushengyuan | 0:2885d4453e88 | 856 | leds = new BusOut(LED4,LED3,LED2,LED1); // for debug |
chushengyuan | 0:2885d4453e88 | 857 | } |
chushengyuan | 0:2885d4453e88 | 858 | |
chushengyuan | 0:2885d4453e88 | 859 | void MMA8452::init() |
chushengyuan | 0:2885d4453e88 | 860 | { |
chushengyuan | 0:2885d4453e88 | 861 | |
chushengyuan | 0:2885d4453e88 | 862 | i2c->frequency(400000); // set Fast Mode I2C frequency (5.10 datasheet) |
chushengyuan | 0:2885d4453e88 | 863 | |
chushengyuan | 0:2885d4453e88 | 864 | char data = readByteFromRegister(WHO_AM_I); // p18 datasheet |
chushengyuan | 0:2885d4453e88 | 865 | if (data != 0x2A) { // if correct ID not found, hand and flash error message |
chushengyuan | 0:2885d4453e88 | 866 | error(); |
chushengyuan | 0:2885d4453e88 | 867 | } |
chushengyuan | 0:2885d4453e88 | 868 | |
chushengyuan | 0:2885d4453e88 | 869 | // put into STANDBY while configuring |
chushengyuan | 0:2885d4453e88 | 870 | data = readByteFromRegister(CTRL_REG1); // get current value of register |
chushengyuan | 0:2885d4453e88 | 871 | data &= ~(1<<0); // clear bit 0 (p37 datasheet) |
chushengyuan | 0:2885d4453e88 | 872 | sendByteToRegister(data,CTRL_REG1); |
chushengyuan | 0:2885d4453e88 | 873 | |
chushengyuan | 0:2885d4453e88 | 874 | // Set output data rate, default is 800 Hz, will set to 100 Hz (clear b5, set b4/b3 - p37 datasheet) |
chushengyuan | 0:2885d4453e88 | 875 | data = readByteFromRegister(CTRL_REG1); |
chushengyuan | 0:2885d4453e88 | 876 | data &= ~(1<<5); |
chushengyuan | 0:2885d4453e88 | 877 | data |= (1<<4); |
chushengyuan | 0:2885d4453e88 | 878 | data |= (1<<3); |
chushengyuan | 0:2885d4453e88 | 879 | sendByteToRegister(data,CTRL_REG1); |
chushengyuan | 0:2885d4453e88 | 880 | |
chushengyuan | 0:2885d4453e88 | 881 | //// Can also change default 2g range to 4g or 8g (p22 datasheet) |
chushengyuan | 0:2885d4453e88 | 882 | data = readByteFromRegister(XYZ_DATA_CFG); |
chushengyuan | 0:2885d4453e88 | 883 | data |= (1<<0); // set bit 0 - 4g range |
chushengyuan | 0:2885d4453e88 | 884 | sendByteToRegister(data,XYZ_DATA_CFG); |
chushengyuan | 0:2885d4453e88 | 885 | |
chushengyuan | 0:2885d4453e88 | 886 | // set ACTIVE |
chushengyuan | 0:2885d4453e88 | 887 | data = readByteFromRegister(CTRL_REG1); |
chushengyuan | 0:2885d4453e88 | 888 | data |= (1<<0); // set bit 0 in CTRL_REG1 |
chushengyuan | 0:2885d4453e88 | 889 | sendByteToRegister(data,CTRL_REG1); |
chushengyuan | 0:2885d4453e88 | 890 | |
chushengyuan | 0:2885d4453e88 | 891 | } |
chushengyuan | 0:2885d4453e88 | 892 | |
chushengyuan | 0:2885d4453e88 | 893 | // read acceleration data from device |
chushengyuan | 0:2885d4453e88 | 894 | Acceleration MMA8452::readValues() |
chushengyuan | 0:2885d4453e88 | 895 | { |
chushengyuan | 0:2885d4453e88 | 896 | // acceleration data stored in 6 registers (0x01 to 0x06) |
chushengyuan | 0:2885d4453e88 | 897 | // device automatically increments register, so can read 6 bytes starting from OUT_X_MSB |
chushengyuan | 0:2885d4453e88 | 898 | char data[6]; |
chushengyuan | 0:2885d4453e88 | 899 | readBytesFromRegister(OUT_X_MSB,6,data); |
chushengyuan | 0:2885d4453e88 | 900 | |
chushengyuan | 0:2885d4453e88 | 901 | char x_MSB = data[0]; // extract MSB and LSBs for x,y,z values |
chushengyuan | 0:2885d4453e88 | 902 | char x_LSB = data[1]; |
chushengyuan | 0:2885d4453e88 | 903 | char y_MSB = data[2]; |
chushengyuan | 0:2885d4453e88 | 904 | char y_LSB = data[3]; |
chushengyuan | 0:2885d4453e88 | 905 | char z_MSB = data[4]; |
chushengyuan | 0:2885d4453e88 | 906 | char z_LSB = data[5]; |
chushengyuan | 0:2885d4453e88 | 907 | |
chushengyuan | 0:2885d4453e88 | 908 | // [0:7] of MSB are 8 MSB of 12-bit value , [7:4] of LSB are 4 LSB's of 12-bit value |
chushengyuan | 0:2885d4453e88 | 909 | // need to type-cast as numbers are in signed (2's complement) form (p20 datasheet) |
chushengyuan | 0:2885d4453e88 | 910 | int x = (int16_t) (x_MSB << 8) | x_LSB; // combine bytes |
chushengyuan | 0:2885d4453e88 | 911 | x >>= 4; // are left-aligned, so shift 4 places right to right-align |
chushengyuan | 0:2885d4453e88 | 912 | int y = (int16_t) (y_MSB << 8) | y_LSB; |
chushengyuan | 0:2885d4453e88 | 913 | y >>= 4; |
chushengyuan | 0:2885d4453e88 | 914 | int z = (int16_t) (z_MSB << 8) | z_LSB; |
chushengyuan | 0:2885d4453e88 | 915 | z >>= 4; |
chushengyuan | 0:2885d4453e88 | 916 | |
chushengyuan | 0:2885d4453e88 | 917 | // sensitivity is 1024 counts/g in 2g mode (pg 9 datasheet) |
chushengyuan | 0:2885d4453e88 | 918 | // " " 512 " 4g " |
chushengyuan | 0:2885d4453e88 | 919 | // " " 256 " 8g " |
chushengyuan | 0:2885d4453e88 | 920 | Acceleration acc; |
chushengyuan | 0:2885d4453e88 | 921 | |
chushengyuan | 0:2885d4453e88 | 922 | acc.x = x/512.0; |
chushengyuan | 0:2885d4453e88 | 923 | acc.y = y/512.0; |
chushengyuan | 0:2885d4453e88 | 924 | acc.z = z/512.0; |
chushengyuan | 0:2885d4453e88 | 925 | |
chushengyuan | 0:2885d4453e88 | 926 | return acc; |
chushengyuan | 0:2885d4453e88 | 927 | } |
chushengyuan | 0:2885d4453e88 | 928 | |
chushengyuan | 0:2885d4453e88 | 929 | // reads a byte from a specific register |
chushengyuan | 0:2885d4453e88 | 930 | char MMA8452::readByteFromRegister(char reg) |
chushengyuan | 0:2885d4453e88 | 931 | { |
chushengyuan | 0:2885d4453e88 | 932 | int nack = i2c->write(MMA8452_W_ADDRESS,®,1,true); // send the register address to the slave |
chushengyuan | 0:2885d4453e88 | 933 | // true as need to send repeated start condition (5.10.1 datasheet) |
chushengyuan | 0:2885d4453e88 | 934 | // http://www.i2c-bus.org/repeated-start-condition/ |
chushengyuan | 0:2885d4453e88 | 935 | if (nack) |
chushengyuan | 0:2885d4453e88 | 936 | error(); // if we don't receive acknowledgement, flash error message |
chushengyuan | 0:2885d4453e88 | 937 | |
chushengyuan | 0:2885d4453e88 | 938 | char rx; |
chushengyuan | 0:2885d4453e88 | 939 | nack = i2c->read(MMA8452_R_ADDRESS,&rx,1); // read a byte from the register and store in buffer |
chushengyuan | 0:2885d4453e88 | 940 | if (nack) |
chushengyuan | 0:2885d4453e88 | 941 | error(); // if we don't receive acknowledgement, flash error message |
chushengyuan | 0:2885d4453e88 | 942 | |
chushengyuan | 0:2885d4453e88 | 943 | return rx; |
chushengyuan | 0:2885d4453e88 | 944 | } |
chushengyuan | 0:2885d4453e88 | 945 | |
chushengyuan | 0:2885d4453e88 | 946 | // reads a series of bytes, starting from a specific register |
chushengyuan | 0:2885d4453e88 | 947 | void MMA8452::readBytesFromRegister(char reg,int numberOfBytes,char bytes[]) |
chushengyuan | 0:2885d4453e88 | 948 | { |
chushengyuan | 0:2885d4453e88 | 949 | |
chushengyuan | 0:2885d4453e88 | 950 | int nack = i2c->write(MMA8452_W_ADDRESS,®,1,true); // send the slave write address and the configuration register address |
chushengyuan | 0:2885d4453e88 | 951 | // true as need to send repeated start condition (5.10.1 datasheet) |
chushengyuan | 0:2885d4453e88 | 952 | // http://www.i2c-bus.org/repeated-start-condition/ |
chushengyuan | 0:2885d4453e88 | 953 | |
chushengyuan | 0:2885d4453e88 | 954 | if (nack) |
chushengyuan | 0:2885d4453e88 | 955 | error(); // if we don't receive acknowledgement, flash error message |
chushengyuan | 0:2885d4453e88 | 956 | |
chushengyuan | 0:2885d4453e88 | 957 | nack = i2c->read(MMA8452_R_ADDRESS,bytes,numberOfBytes); // read bytes |
chushengyuan | 0:2885d4453e88 | 958 | if (nack) |
chushengyuan | 0:2885d4453e88 | 959 | error(); // if we don't receive acknowledgement, flash error message |
chushengyuan | 0:2885d4453e88 | 960 | |
chushengyuan | 0:2885d4453e88 | 961 | } |
chushengyuan | 0:2885d4453e88 | 962 | |
chushengyuan | 0:2885d4453e88 | 963 | // sends a byte to a specific register |
chushengyuan | 0:2885d4453e88 | 964 | void MMA8452::sendByteToRegister(char byte,char reg) |
chushengyuan | 0:2885d4453e88 | 965 | { |
chushengyuan | 0:2885d4453e88 | 966 | char data[2]; |
chushengyuan | 0:2885d4453e88 | 967 | data[0] = reg; |
chushengyuan | 0:2885d4453e88 | 968 | data[1] = byte; |
chushengyuan | 0:2885d4453e88 | 969 | // send the register address, followed by the data |
chushengyuan | 0:2885d4453e88 | 970 | int nack = i2c->write(MMA8452_W_ADDRESS,data,2); |
chushengyuan | 0:2885d4453e88 | 971 | if (nack) |
chushengyuan | 0:2885d4453e88 | 972 | error(); // if we don't receive acknowledgement, flash error message |
chushengyuan | 0:2885d4453e88 | 973 | |
chushengyuan | 0:2885d4453e88 | 974 | } |
chushengyuan | 0:2885d4453e88 | 975 | |
chushengyuan | 0:2885d4453e88 | 976 | void MMA8452::error() |
chushengyuan | 0:2885d4453e88 | 977 | { |
chushengyuan | 0:2885d4453e88 | 978 | while(1) { |
chushengyuan | 0:2885d4453e88 | 979 | leds->write(15); |
chushengyuan | 0:2885d4453e88 | 980 | wait(0.1); |
chushengyuan | 0:2885d4453e88 | 981 | leds->write(0); |
chushengyuan | 0:2885d4453e88 | 982 | wait(0.1); |
chushengyuan | 0:2885d4453e88 | 983 | } |
chushengyuan | 0:2885d4453e88 | 984 | } |
chushengyuan | 0:2885d4453e88 | 985 | |
chushengyuan | 0:2885d4453e88 | 986 | |
chushengyuan | 0:2885d4453e88 | 987 | |
chushengyuan | 0:2885d4453e88 | 988 |