rotating degree, orientation direction, digital protractor and falling alert.
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 /************************************** 00002 Multifunction Protractor code mian.cpp file 00003 by ren ping 00004 EEE department student 00005 university of leeds 00006 1 may 2015 00007 **************************************/ 00008 #include "mbed.h" 00009 #include "N5110.h" 00010 #include "MMA8452.h" 00011 #include <stdlib.h> 00012 #include <math.h> /* asin */ 00013 #include <cmath> 00014 00015 #include<iostream> 00016 00017 using namespace std; 00018 00019 00020 #define UP 0 //define Button UP state 00021 #define DOWN 1 //define Button UP state 00022 #define PI 3.14 //define constant variable PI 00023 00024 00025 MMA8452 mma8452(p28,p27); // pin number for SDA, SCL 00026 Serial serial(USBTX,USBRX); 00027 N5110 lcd(p7,p8,p9,p10,p11,p13,p26); // pin numbers for VCC,SCE,RST,D/C,MOSI,SCLK,LED 00028 00029 /* pin number for led,buzzer amd buttons */ 00030 BusOut ledx(p23); 00031 BusOut ledy(p24); 00032 BusOut ledz(p25); 00033 DigitalOut buzzer(p14); 00034 InterruptIn button1(p22); 00035 InterruptIn button2(p21); 00036 /* initial button direction */ 00037 int direction1 = 0; 00038 int direction2 = 0; 00039 /* initial LEDs and Buzzer state */ 00040 int on = 1; 00041 int off = 0; 00042 /* tickers for leds and buzzer */ 00043 Ticker ledx_time; 00044 Ticker ledy_time; 00045 Ticker ledz_time; 00046 Ticker buzzer_time; 00047 /* button pressed function */ 00048 void button1Pressed() 00049 { 00050 direction1=!direction1; 00051 } 00052 void button2Pressed() 00053 { 00054 direction2=!direction2; 00055 } 00056 00057 /* tickers functions for leds and buzzer */ 00058 void timer_handler_buzzer() 00059 { 00060 buzzer = buzzer ^ 1; // invert the buzzer value 00061 } 00062 00063 void timer_handler_ledx() 00064 { 00065 ledx = ledx ^ 1; // invert the buzzer value 00066 } 00067 00068 void timer_handler_ledy() 00069 { 00070 ledy= ledy ^ 1; // invert the buzzer value 00071 } 00072 00073 void timer_handler_ledz() 00074 { 00075 ledz= ledz ^ 1; // invert the buzzer value 00076 } 00077 00078 int main() 00079 { 00080 lcd.setBrightness(0.05);// put LED backlight on 5% 00081 00082 button1.rise(&button1Pressed);//button rise detector and call the "button pressed function" 00083 button2.rise(&button2Pressed); 00084 00085 //button pressed counter and flag 00086 int m=1; 00087 int n=1; 00088 int numflag; 00089 00090 //variable of angle 00091 float g1; //starting angle 00092 float g2; //ending angle 00093 float gd; //difference between starting and ending angle 00094 00095 while(1) { 00096 00097 lcd.init(); // lcd initial state 00098 lcd.normalMode(); // normal colour mode 00099 mma8452.init(); // 100 Hz update rate, ±4g scale 00100 Acceleration acceleration;// Accleration structure declared in MMA8452 class 00101 acceleration = mma8452.readValues(); // read current values and print over serial port 00102 00103 00104 ////////////////////////////////////// draw horizontal reference line 00105 for (int i = 0; i < 28; i++) { 00106 lcd.setPixel(i,24); 00107 } 00108 for (int i = 54; i < WIDTH; i++) { 00109 lcd.setPixel(i,24); 00110 } 00111 ////////////////////////////////////// draw vertical reference line 00112 for (int i =8 ; i < 13; i++) { 00113 lcd.setPixel(41,i); 00114 } 00115 00116 for (int i = 33; i < 38; i++) { 00117 lcd.setPixel(41,i); 00118 } 00119 00120 00121 lcd.setPixel(41,24);//draw centeral reference point 00122 00123 /////////////////////////////////////////////////////////////variable initial 00124 float xy90=90.0;//constant variable 00125 00126 float x1=asin(abs(acceleration.x))*180.00/PI;//using x axis accerleration value to calculate y-axis rotating angle 00127 float y1=asin(abs(acceleration.y))*180.00/PI;//using y-axis accerleration value to calculate x-axis rotating angle 00128 float z1=asin(abs(acceleration.z))*180.00/PI;//using z-axis accerleration value to calculate z-axis rotating angle 00129 00130 // initial buffers to LCD 00131 char buffer1[14]; 00132 char buffer2[14]; 00133 char buffer3[14]; 00134 char buffer4[14]; 00135 char buffer5[14]; 00136 char buffer6[14]; 00137 00138 /////////////////////////////////Falling alert mode////////////////////////////////// 00139 switch(direction2) { 00140 00141 case DOWN:// button "B" pressed 00142 lcd.printString("ON",0,0);// print "ON" on lcd display 00143 00144 ////// LED_X_axis if statement judgement////// 00145 if(x1>=50) {//when y-axis rotating angle is bigger than 50 degree, xled is blinking 00146 ledx=1; 00147 ledx_time.attach(&timer_handler_ledx, 1);// Every 1s call the timer_handler function 00148 } else if(x1<=50) {//when y-axis rotating angle is less than 50 degree, xled is off 00149 ledx=0;//led_x off 00150 ledx_time.attach(&timer_handler_ledx, 0.0);//stop calling the timer_handler function 00151 } 00152 00153 00154 ////// LED_Y_axis if statement judgement////// 00155 if(y1>=50) {//when x-axis rotating angle is bigger than 50 degree, yled is blinking 00156 ledy=1; 00157 ledy_time.attach(&timer_handler_ledy, 1);// Every 1s call the timer_handler function 00158 } else if(y1<=50) {//when x-axis rotating angle is less than 50 degree, yled is blinking 00159 ledy=0;//;ed_y off 00160 ledx_time.attach(&timer_handler_ledx, 0.0);//stop calling the timer_handler function 00161 } 00162 00163 ////// LED_Z_axis if statement judgement////// 00164 if(acceleration.z<=0 ) { 00165 ledz=1; 00166 buzzer = 0; // initialize buzzer 00167 buzzer_time.attach(&timer_handler_buzzer, 0.5);// Every 0.5s call the timer_handler_buzzer function 00168 } else if(acceleration.z>=0) { 00169 ledz=0;//led_z off 00170 buzzer = 0;//buzzer off 00171 buzzer_time.attach(&timer_handler_buzzer, 0.0);//stop calling the timer_handler function 00172 } 00173 break; 00174 00175 case UP:// button"B" state is off 00176 lcd.printString("OFF",0,0);// print "OFF" on lcd display 00177 //set all leds and buzzer off, stop call the time_handler_function 00178 ledx=0; 00179 ledy=0; 00180 ledz=0; 00181 buzzer=0; 00182 buzzer_time.attach(&timer_handler_buzzer,0.0); 00183 ledx_time.attach(&timer_handler_ledx,0.0); 00184 ledy_time.attach(&timer_handler_ledy,0.0); 00185 ledz_time.attach(&timer_handler_ledz,0.0); 00186 break; 00187 } 00188 00189 ///////////////////////////////debug when acceleration is bigger than 1 of less than -1/////////////////////////////////////////////////// 00190 00191 if(abs(acceleration.x)<=1) { 00192 int length1 = sprintf(buffer1,"%.1f",x1); 00193 } else if(abs(acceleration.x)>=1) { 00194 int length1 = sprintf(buffer1,"%.1f",xy90); 00195 }//set 90 degree when acceleration is bigger than 1 or less than -1 00196 00197 00198 if(abs(acceleration.y)<=1) { 00199 int length2 = sprintf(buffer2,"%.1f",y1); 00200 } else if(abs(acceleration.y)>=1) { 00201 int length2 = sprintf(buffer2,"%.1f",xy90); 00202 }//set 90 degree when acceleration is bigger than 1 or less than -1 00203 00204 ////////////////////////////////print orientation direction capatial letter and rotating degree///////////////////////////////////// 00205 if(acceleration.y>0) { 00206 lcd.printString("F",39,0); 00207 lcd.printString(buffer2,46,0); 00208 } else if(acceleration.y<0) { 00209 lcd.printString("B",39,5); 00210 lcd.printString(buffer2,46,5); 00211 } 00212 00213 if(acceleration.z>0) { 00214 lcd.printString("UP",36,2); 00215 } else if(acceleration.z<0) { 00216 lcd.printString("DOWN",30,3); 00217 } 00218 00219 00220 /////////////////////////////////Protractor mode/////////////////////////////////////////////////////////////////////////// 00221 if(acceleration.x>0) {//when system rotates to right side 00222 switch(direction1) { 00223 case UP://button "A" OFF state 00224 //pring "R" and rotating degree 00225 lcd.printString("R",78,2); 00226 lcd.printString(buffer1,53,2); 00227 break; 00228 00229 case DOWN://button "A" ON state 00230 //button click counter and set button click flag 00231 if(m%2 == 1) { 00232 numflag=1;//set flag 1 when button click counter is odd number 00233 } else if(m%2 == 0) { 00234 numflag=2;//set flag 2 when button click counter is even number 00235 } else if(m==0) {//when button counter is 0, pring "R" and rotating degree 00236 lcd.printString("R",78,2); 00237 lcd.printString(buffer1,53,2); 00238 } 00239 00240 switch(numflag) {//numberflag switch 00241 case 1:// when the button click counter is odd number 00242 g1=asin(abs(acceleration.x))*180.0/PI;//get curretn rotating degree as starting degree 00243 int length3= sprintf(buffer3,"%.1f",g1);//print the degree 00244 break; 00245 00246 case 2:// when the button click counter is even number 00247 g2=asin(abs(acceleration.x))*180.0/PI;//get curretn rotating degree as ending degree 00248 gd=g2-g1;//calculate the difference between the starting degree and ending degree 00249 int length4= sprintf(buffer4,"%.1f",gd);//print degree difference 00250 break; 00251 } 00252 direction1=0;//button direction switch 00253 m=m+1;//button counter add 00254 }// pring value 00255 lcd.printString("R",78,2); 00256 lcd.printString(buffer1,53,2); 00257 lcd.printString(buffer3,53,1); 00258 lcd.printString(buffer4,53,4); 00259 00260 } else if(acceleration.x<0) {//when system rotates to left 00261 00262 switch(direction1) { 00263 case UP://button "A" is in OFF state 00264 lcd.printString("L",1,2); 00265 lcd.printString(buffer1,8,2); 00266 break; 00267 00268 case DOWN://button "A" is in ON state 00269 if(n%2 == 1) { 00270 numflag=1;//set flag 1 when button click counter is odd number 00271 } else if(n%2 == 0) { 00272 numflag=2;//set flag 2 when button click counter is even number 00273 } else if(n==0) {//when button counter is 0, pring "L" and rotating degree 00274 lcd.printString("L",1,2); 00275 lcd.printString(buffer1,8,2); 00276 } 00277 00278 switch(numflag) {//numberflag switch 00279 00280 case 1:// when the button click counter is odd number 00281 g1=asin(abs(acceleration.x))*180.0/PI;//get curretn rotating degree as starting degree 00282 int length5= sprintf(buffer5,"%.1f",g1);//print the degree 00283 break; 00284 00285 case 2: 00286 g2=asin(abs(acceleration.x))*180.0/PI;; 00287 gd=g2-g1;//calculate the difference between the starting degree and ending degree 00288 int length6= sprintf(buffer6,"%.1f",gd);//print the degree difference 00289 break; 00290 } 00291 direction1=0;//switch the button direction 00292 n=n+1;//button click add 00293 break; 00294 }// pring value 00295 lcd.printString("L",1,2); 00296 lcd.printString(buffer1,8,2); 00297 lcd.printString(buffer5,8,1); 00298 lcd.printString(buffer6,8,4); 00299 } 00300 wait(0.1); 00301 lcd.refresh(); 00302 lcd.clear(); 00303 00304 }; 00305 } 00306 00307 00308 00309 /////////////////////////////////////////////// functions for N5110//////////////////////////////////////////////////////////////////////////////////////////////// 00310 N5110::N5110(PinName p7, PinName p8, PinName p9, PinName p10, PinName p11, PinName p13, PinName p26) 00311 { 00312 00313 spi = new SPI(p11,NC,p13); // create new SPI instance and initialise 00314 initSPI(); 00315 00316 // set up pins as required 00317 led = new PwmOut(p26); 00318 pwr = new DigitalOut(p7); 00319 sce = new DigitalOut(p8); 00320 rst = new DigitalOut(p9); 00321 dc = new DigitalOut(p10); 00322 00323 } 00324 00325 // initialise function - powers up and sends the initialisation commands 00326 void N5110::init() 00327 { 00328 turnOn(); // power up 00329 wait_ms(10); // small delay seems to prevent spurious pixels during mbed reset 00330 reset(); // reset LCD - must be done within 100 ms 00331 00332 // function set - extended 00333 sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_EXTENDED_MODE); 00334 // Don't completely understand these parameters - they seem to work as they are 00335 // Consult the datasheet if you need to change them 00336 sendCommand(CMD_VOP_7V38); // operating voltage - these values are from Chris Yan's Library 00337 sendCommand(CMD_TC_TEMP_2); // temperature control 00338 sendCommand(CMD_BI_MUX_48); // bias 00339 00340 // function set - basic 00341 sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_BASIC_MODE); 00342 normalMode(); // normal video mode by default 00343 sendCommand(CMD_DC_NORMAL_MODE); // black on white 00344 00345 // RAM is undefined at power-up so clear 00346 clearRAM(); 00347 00348 } 00349 00350 // sets normal video mode (black on white) 00351 void N5110::normalMode() 00352 { 00353 sendCommand(CMD_DC_NORMAL_MODE); 00354 00355 } 00356 00357 // sets normal video mode (white on black) 00358 void N5110::inverseMode() 00359 { 00360 sendCommand(CMD_DC_INVERT_VIDEO); 00361 } 00362 00363 // function to power up the LCD and backlight 00364 void N5110::turnOn() 00365 { 00366 // set brightness of LED - 0.0 to 1.0 - default is 50% 00367 setBrightness(0.5); 00368 pwr->write(1); // apply power 00369 } 00370 00371 // function to power down LCD 00372 void N5110::turnOff() 00373 { 00374 setBrightness(0.0); // turn backlight off 00375 clearRAM(); // clear RAM to ensure specified current consumption 00376 // send command to ensure we are in basic mode 00377 sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_BASIC_MODE); 00378 // clear the display 00379 sendCommand(CMD_DC_CLEAR_DISPLAY); 00380 // enter the extended mode and power down 00381 sendCommand(0x20 | CMD_FS_POWER_DOWN_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_EXTENDED_MODE); 00382 // small delay and then turn off the power pin 00383 wait_ms(10); 00384 pwr->write(0); 00385 00386 } 00387 00388 // function to change LED backlight brightness 00389 void N5110::setBrightness(float brightness) 00390 { 00391 // check whether brightness is within range 00392 if (brightness < 0.0) 00393 brightness = 0.0; 00394 if (brightness > 1.0) 00395 brightness = 1.0; 00396 // set PWM duty cycle 00397 led->write(brightness); 00398 } 00399 00400 00401 // pulse the active low reset line 00402 void N5110::reset() 00403 { 00404 rst->write(0); // reset the LCD 00405 rst->write(1); 00406 } 00407 00408 // function to initialise SPI peripheral 00409 void N5110::initSPI() 00410 { 00411 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 00412 spi->frequency(4000000); // maximum of screen is 4 MHz 00413 } 00414 00415 // send a command to the display 00416 void N5110::sendCommand(unsigned char command) 00417 { 00418 dc->write(0); // set DC low for command 00419 sce->write(0); // set CE low to begin frame 00420 spi->write(command); // send command 00421 dc->write(1); // turn back to data by default 00422 sce->write(1); // set CE high to end frame (expected for transmission of single byte) 00423 00424 } 00425 00426 // send data to the display at the current XY address 00427 // dc is set to 1 (i.e. data) after sending a command and so should 00428 // be the default mode. 00429 void N5110::sendData(unsigned char data) 00430 { 00431 sce->write(0); // set CE low to begin frame 00432 spi->write(data); 00433 sce->write(1); // set CE high to end frame (expected for transmission of single byte) 00434 } 00435 00436 // this function writes 0 to the 504 bytes to clear the RAM 00437 void N5110::clearRAM() 00438 { 00439 int i; 00440 sce->write(0); //set CE low to begin frame 00441 for(i = 0; i < WIDTH * HEIGHT; i++) { // 48 x 84 bits = 504 bytes 00442 spi->write(0x00); // send 0's 00443 } 00444 sce->write(1); // set CE high to end frame 00445 00446 } 00447 00448 // function to set the XY address in RAM for subsequenct data write 00449 void N5110::setXYAddress(int x, int y) 00450 { 00451 if (x>=0 && x<WIDTH && y>=0 && y<HEIGHT) { // check within range 00452 sendCommand(0x80 | x); // send addresses to display with relevant mask 00453 sendCommand(0x40 | y); 00454 } 00455 } 00456 00457 // These functions are used to set, clear and get the value of pixels in the display 00458 // Pixels are addressed in the range of 0 to 47 (y) and 0 to 83 (x). The refresh() 00459 // function must be called after set and clear in order to update the display 00460 void N5110::setPixel(int x, int y) 00461 { 00462 if (x>=0 && x<WIDTH && y>=0 && y<HEIGHT) { // check within range 00463 // calculate bank and shift 1 to required position in the data byte 00464 buffer[x][y/8] |= (1 << y%8); 00465 } 00466 } 00467 00468 void N5110::clearPixel(int x, int y) 00469 { 00470 if (x>=0 && x<WIDTH && y>=0 && y<HEIGHT) { // check within range 00471 // calculate bank and shift 1 to required position (using bit clear) 00472 buffer[x][y/8] &= ~(1 << y%8); 00473 } 00474 } 00475 00476 int N5110::getPixel(int x, int y) 00477 { 00478 if (x>=0 && x<WIDTH && y>=0 && y<HEIGHT) { // check within range 00479 // return relevant bank and mask required bit 00480 return (int) buffer[x][y/8] & (1 << y%8); 00481 // note this does not necessarily return 1 - a non-zero number represents a pixel 00482 } else { 00483 return 0; 00484 } 00485 } 00486 00487 // function to refresh the display 00488 void N5110::refresh() 00489 { 00490 int i,j; 00491 00492 setXYAddress(0,0); // important to set address back to 0,0 before refreshing display 00493 // address auto increments after printing string, so buffer[0][0] will not coincide 00494 // with top-left pixel after priting string 00495 00496 sce->write(0); //set CE low to begin frame 00497 00498 for(j = 0; j < BANKS; j++) { // be careful to use correct order (j,i) for horizontal addressing 00499 for(i = 0; i < WIDTH; i++) { 00500 spi->write(buffer[i][j]); // send buffer 00501 } 00502 } 00503 sce->write(1); // set CE high to end frame 00504 00505 } 00506 00507 // fills the buffer with random bytes. Can be used to test the display. 00508 // The rand() function isn't seeded so it probably creates the same pattern everytime 00509 void N5110::randomiseBuffer() 00510 { 00511 int i,j; 00512 for(j = 0; j < BANKS; j++) { // be careful to use correct order (j,i) for horizontal addressing 00513 for(i = 0; i < WIDTH; i++) { 00514 buffer[i][j] = rand()%256; // generate random byte 00515 } 00516 } 00517 00518 } 00519 00520 // function to print 5x7 font 00521 void N5110::printChar(char c,int x,int y) 00522 { 00523 if (y>=0 && y<BANKS) { // check if printing in range of y banks 00524 00525 for (int i = 0; i < 5 ; i++ ) { 00526 int pixel_x = x+i; 00527 if (pixel_x > WIDTH-1) // ensure pixel isn't outside the buffer size (0 - 83) 00528 break; 00529 buffer[pixel_x][y] = font5x7[(c - 32)*5 + i]; 00530 // array is offset by 32 relative to ASCII, each character is 5 pixels wide 00531 } 00532 00533 refresh(); // this sends the buffer to the display and sets address (cursor) back to 0,0 00534 } 00535 } 00536 00537 // function to print string at specified position 00538 void N5110::printString(const char * str,int x,int y) 00539 { 00540 if (y>=0 && y<BANKS) { // check if printing in range of y banks 00541 00542 int n = 0 ; // counter for number of characters in string 00543 // loop through string and print character 00544 while(*str) { 00545 00546 // writes the character bitmap data to the buffer, so that 00547 // text and pixels can be displayed at the same time 00548 for (int i = 0; i < 5 ; i++ ) { 00549 int pixel_x = x+i+n*6; 00550 if (pixel_x > WIDTH-1) // ensure pixel isn't outside the buffer size (0 - 83) 00551 break; 00552 buffer[pixel_x][y] = font5x7[(*str - 32)*5 + i]; 00553 } 00554 00555 str++; // go to next character in string 00556 00557 n++; // increment index 00558 00559 } 00560 00561 refresh(); // this sends the buffer to the display and sets address (cursor) back to 0,0 00562 } 00563 } 00564 00565 // function to clear the screen 00566 void N5110::clear() 00567 { 00568 clearBuffer(); // clear the buffer then call the refresh function 00569 refresh(); 00570 } 00571 00572 // function to clear the buffer 00573 void N5110::clearBuffer() 00574 { 00575 int i,j; 00576 for (i=0; i<WIDTH; i++) { // loop through the banks and set the buffer to 0 00577 for (j=0; j<BANKS; j++) { 00578 buffer[i][j]=0; 00579 } 00580 } 00581 } 00582 00583 // function to plot array on display 00584 void N5110::plotArray(float array[]) 00585 { 00586 00587 int i; 00588 00589 for (i=0; i<WIDTH; i++) { // loop through array 00590 // elements are normalised from 0.0 to 1.0, so multiply 00591 // by 47 to convert to pixel range, and subtract from 47 00592 // since top-left is 0,0 in the display geometry 00593 setPixel(i,47 - int(array[i]*47.0)); 00594 } 00595 00596 refresh(); 00597 00598 } 00599 00600 // function to draw circle 00601 void N5110:: drawCircle(int x0,int y0,int radius,int fill) 00602 { 00603 // from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm 00604 int x = radius; 00605 int y = 0; 00606 int radiusError = 1-x; 00607 00608 while(x >= y) { 00609 00610 // if transparent, just draw outline 00611 if (fill == 0) { 00612 setPixel( x + x0, y + y0); 00613 setPixel(-x + x0, y + y0); 00614 setPixel( y + x0, x + y0); 00615 setPixel(-y + x0, x + y0); 00616 setPixel(-y + x0, -x + y0); 00617 setPixel( y + x0, -x + y0); 00618 setPixel( x + x0, -y + y0); 00619 setPixel(-x + x0, -y + y0); 00620 } else { // drawing filled circle, so draw lines between points at same y value 00621 00622 int type = (fill==1) ? 1:0; // black or white fill 00623 00624 drawLine(x+x0,y+y0,-x+x0,y+y0,type); 00625 drawLine(y+x0,x+y0,-y+x0,x+y0,type); 00626 drawLine(y+x0,-x+y0,-y+x0,-x+y0,type); 00627 drawLine(x+x0,-y+y0,-x+x0,-y+y0,type); 00628 } 00629 00630 00631 y++; 00632 if (radiusError<0) { 00633 radiusError += 2 * y + 1; 00634 } else { 00635 x--; 00636 radiusError += 2 * (y - x) + 1; 00637 } 00638 } 00639 00640 } 00641 00642 void N5110::drawLine(int x0,int y0,int x1,int y1,int type) 00643 { 00644 int y_range = y1-y0; // calc range of y and x 00645 int x_range = x1-x0; 00646 int start,stop,step; 00647 00648 // if dotted line, set step to 2, else step is 1 00649 step = (type==2) ? 2:1; 00650 00651 // make sure we loop over the largest range to get the most pixels on the display 00652 // for instance, if drawing a vertical line (x_range = 0), we need to loop down the y pixels 00653 // or else we'll only end up with 1 pixel in the x column 00654 if ( abs(x_range) > abs(y_range) ) { 00655 00656 // ensure we loop from smallest to largest or else for-loop won't run as expected 00657 start = x1>x0 ? x0:x1; 00658 stop = x1>x0 ? x1:x0; 00659 00660 // loop between x pixels 00661 for (int x = start; x<= stop ; x+=step) { 00662 // do linear interpolation 00663 int y = y0 + (y1-y0)*(x-x0)/(x1-x0); 00664 00665 if (type == 0) // if 'white' line, turn off pixel 00666 clearPixel(x,y); 00667 else 00668 setPixel(x,y); // else if 'black' or 'dotted' turn on pixel 00669 } 00670 } else { 00671 00672 // ensure we loop from smallest to largest or else for-loop won't run as expected 00673 start = y1>y0 ? y0:y1; 00674 stop = y1>y0 ? y1:y0; 00675 00676 for (int y = start; y<= stop ; y+=step) { 00677 // do linear interpolation 00678 int x = x0 + (x1-x0)*(y-y0)/(y1-y0); 00679 00680 if (type == 0) // if 'white' line, turn off pixel 00681 clearPixel(x,y); 00682 else 00683 setPixel(x,y); // else if 'black' or 'dotted' turn on pixel 00684 00685 } 00686 } 00687 00688 } 00689 00690 void N5110::drawRect(int x0,int y0,int width,int height,int fill) 00691 { 00692 00693 if (fill == 0) { // transparent, just outline 00694 drawLine(x0,y0,x0+width,y0,1); // top 00695 drawLine(x0,y0+height,x0+width,y0+height,1); // bottom 00696 drawLine(x0,y0,x0,y0+height,1); // left 00697 drawLine(x0+width,y0,x0+width,y0+height,1); // right 00698 } else { // filled rectangle 00699 int type = (fill==1) ? 1:0; // black or white fill 00700 for (int y = y0; y<= y0+height; y++) { // loop through rows of rectangle 00701 drawLine(x0,y,x0+width,y,type); // draw line across screen 00702 } 00703 } 00704 00705 } 00706 00707 00708 00709 //////////////////////////////////////////////////////////////////////////////////////functions for MMA8452//////////////////////////////////////////////// 00710 MMA8452:: MMA8452(PinName p28, PinName p27) 00711 { 00712 i2c = new I2C(p28,p27); // create new I2C instance and initialise 00713 i2c->frequency(800000); // I2C Fast Mode - 400kHz 00714 leds = new BusOut(LED4,LED3,LED2,LED1); // for debug 00715 } 00716 00717 void MMA8452::init() 00718 { 00719 00720 i2c->frequency(800000); // set Fast Mode I2C frequency (5.10 datasheet) 00721 00722 char data = readByteFromRegister(WHO_AM_I); // p18 datasheet 00723 if (data != 0x2A) { // if correct ID not found, hand and flash error message 00724 error(); 00725 } 00726 00727 // put into STANDBY while configuring 00728 data = readByteFromRegister(CTRL_REG1); // get current value of register 00729 data &= ~(1<<0); // clear bit 0 (p37 datasheet) 00730 sendByteToRegister(data,CTRL_REG1); 00731 00732 // Set output data rate, default is 800 Hz, will set to 100 Hz (clear b5, set b4/b3 - p37 datasheet) 00733 data = readByteFromRegister(CTRL_REG1); 00734 data &= ~(1<<5); 00735 data |= (1<<4); 00736 data |= (1<<3); 00737 sendByteToRegister(data,CTRL_REG1); 00738 00739 //// Can also change default 2g range to 4g or 8g (p22 datasheet) 00740 data = readByteFromRegister(XYZ_DATA_CFG); 00741 data |= (1<<0); // set bit 0 - 4g range 00742 sendByteToRegister(data,XYZ_DATA_CFG); 00743 00744 // set ACTIVE 00745 data = readByteFromRegister(CTRL_REG1); 00746 data |= (1<<0); // set bit 0 in CTRL_REG1 00747 sendByteToRegister(data,CTRL_REG1); 00748 00749 } 00750 00751 // read acceleration data from device 00752 Acceleration MMA8452::readValues() 00753 { 00754 // acceleration data stored in 6 registers (0x01 to 0x06) 00755 // device automatically increments register, so can read 6 bytes starting from OUT_X_MSB 00756 char data[6]; 00757 readBytesFromRegister(OUT_X_MSB,6,data); 00758 00759 char x_MSB = data[0]; // extract MSB and LSBs for x,y,z values 00760 char x_LSB = data[1]; 00761 char y_MSB = data[2]; 00762 char y_LSB = data[3]; 00763 char z_MSB = data[4]; 00764 char z_LSB = data[5]; 00765 00766 // [0:7] of MSB are 8 MSB of 12-bit value , [7:4] of LSB are 4 LSB's of 12-bit value 00767 // need to type-cast as numbers are in signed (2's complement) form (p20 datasheet) 00768 int x = (int16_t) (x_MSB << 8) | x_LSB; // combine bytes 00769 x >>= 4; // are left-aligned, so shift 4 places right to right-align 00770 int y = (int16_t) (y_MSB << 8) | y_LSB; 00771 y >>= 4; 00772 int z = (int16_t) (z_MSB << 8) | z_LSB; 00773 z >>= 4; 00774 00775 // sensitivity is 1024 counts/g in 2g mode (pg 9 datasheet) 00776 // " " 512 " 4g " 00777 // " " 256 " 8g " 00778 Acceleration acc; 00779 00780 acc.x = x/512.0; 00781 acc.y = y/512.0; 00782 acc.z = z/512.0; 00783 00784 return acc; 00785 } 00786 00787 // reads a byte from a specific register 00788 char MMA8452::readByteFromRegister(char reg) 00789 { 00790 int nack = i2c->write(MMA8452_W_ADDRESS,®,1,true); // send the register address to the slave 00791 // true as need to send repeated start condition (5.10.1 datasheet) 00792 // http://www.i2c-bus.org/repeated-start-condition/ 00793 if (nack) 00794 error(); // if we don't receive acknowledgement, flash error message 00795 00796 char rx; 00797 nack = i2c->read(MMA8452_R_ADDRESS,&rx,1); // read a byte from the register and store in buffer 00798 if (nack) 00799 error(); // if we don't receive acknowledgement, flash error message 00800 00801 return rx; 00802 } 00803 00804 // reads a series of bytes, starting from a specific register 00805 void MMA8452::readBytesFromRegister(char reg,int numberOfBytes,char bytes[]) 00806 { 00807 00808 int nack = i2c->write(MMA8452_W_ADDRESS,®,1,true); // send the slave write address and the configuration register address 00809 // true as need to send repeated start condition (5.10.1 datasheet) 00810 // http://www.i2c-bus.org/repeated-start-condition/ 00811 00812 if (nack) 00813 error(); // if we don't receive acknowledgement, flash error message 00814 00815 nack = i2c->read(MMA8452_R_ADDRESS,bytes,numberOfBytes); // read bytes 00816 if (nack) 00817 error(); // if we don't receive acknowledgement, flash error message 00818 00819 } 00820 00821 // sends a byte to a specific register 00822 void MMA8452::sendByteToRegister(char byte,char reg) 00823 { 00824 char data[2]; 00825 data[0] = reg; 00826 data[1] = byte; 00827 // send the register address, followed by the data 00828 int nack = i2c->write(MMA8452_W_ADDRESS,data,2); 00829 if (nack) 00830 error(); // if we don't receive acknowledgement, flash error message 00831 00832 } 00833 00834 void MMA8452::error() 00835 { 00836 while(1) { 00837 leds->write(15); 00838 wait(0.1); 00839 leds->write(0); 00840 wait(0.1); 00841 } 00842 }
Generated on Thu Jul 14 2022 01:58:51 by
1.7.2