rotating degree, orientation direction, digital protractor and falling alert.

Dependencies:   MMA8452 mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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,&reg,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,&reg,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 }