Aleksandar Kodzhabashev / Mbed 2 deprecated TrackballQuery

Dependencies:   Servo mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PS2MS.cpp Source File

PS2MS.cpp

00001 /**
00002  * PS/2 mouse interface control class (Version 0.0.1)
00003  *
00004  * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
00005  * http://shinta.main.jp/
00006  */
00007 
00008 #include "PS2MS.h"
00009 
00010 #define DEBUG false
00011 
00012 /**
00013  * Create.
00014  *
00015  * @param clk_pin Clock pin.
00016  * @param dat_pin Data pin.
00017  */
00018 PS2MS::PS2MS(PinName clk_pin, PinName dat_pin)
00019     : clk(clk_pin), dat(dat_pin), clkOut(clk_pin), mSending(false), mInFuncFall(false)
00020 {
00021     init_work();
00022     dat.input();
00023     clk.fall(this, &PS2MS::func_fall);
00024     timeout = 1;
00025 }
00026 
00027 /**
00028  * Destory.
00029  */
00030 PS2MS::~PS2MS()
00031 {
00032     wdt.detach();
00033 }
00034 
00035 int PS2MS::getc()
00036 {
00037     tot.reset();
00038     tot.start();
00039     while (work.cStart == work.cEnd) {
00040         wait_ms(1);
00041         if ((timeout > 0) && (tot.read_ms() > timeout)) {
00042             return EOF;
00043         }
00044     }
00045     tot.stop();
00046 
00047     char c = work.buffer[work.cStart++];
00048     work.cStart =  work.cStart % RINGBUFSIZ;
00049 
00050     return c;
00051 }
00052 
00053 
00054 
00055 int PS2MS::sendCommand(char c)
00056 {
00057     while (mInFuncFall) {
00058         continue;
00059     }
00060     mSending = true;
00061     if (DEBUG) printf("S ");
00062     dat.output();
00063     clkOut.output();
00064     clkOut.write(0);
00065     wait_us(200);
00066 
00067     dat.write(0);
00068     wait_us(10);
00069     clkOut.write(1);
00070     clkOut.input();
00071 
00072     int parcnt = 0;
00073     for (int i = 0; i < 10; i++) {
00074         if (!waitClockDownEdge()) {
00075             mSending = false;
00076             wait_us(50);
00077             if (DEBUG) printf("R ");
00078             return -1;
00079         }
00080         if ((0 <= i) && (i <= 7)) {
00081             /*
00082              * Data bit.
00083              */
00084             if ((c & (1 << i)) == 0) {
00085                 dat.write(0);
00086             } else {
00087                 dat.write(1);
00088                 parcnt++;
00089             }
00090         }
00091         if (i == 8) {
00092             /*
00093              * Parity bit.
00094              */
00095             if ((parcnt % 2) == 0) {
00096                 dat.write(1);
00097             } else {
00098                 dat.write(0);
00099             }
00100         }
00101         if (i == 9) {
00102             /*
00103              * Stop bit.
00104              */
00105             dat.write(1);
00106         }
00107     }
00108 
00109     dat.input();
00110     /*
00111      * Check a ACK.
00112      */
00113     if (!waitClockDownEdge()) {
00114         mSending = false;
00115         wait_us(50);
00116         if (DEBUG) printf("R ");
00117         return -2;
00118     }
00119     if (dat.read() != 0) {
00120         mSending = false;
00121         wait_us(50);
00122         if (DEBUG) printf("R ");
00123         return -3;
00124     }
00125 
00126     if (!waitClockUpLevel()) {
00127         mSending = false;
00128         wait_us(50);
00129         if (DEBUG) printf("R ");
00130         return -4;
00131     }
00132     mSending = false;
00133     if (DEBUG) printf("E ");
00134     wait_us(50);
00135 
00136     return 0;
00137 }
00138 
00139 /**
00140  * Wait a clock up level.
00141  *
00142  * @return true if wait done.
00143  */
00144 bool PS2MS::waitClockUpLevel(void)
00145 {
00146     int cnt;
00147     /*
00148      * Wait until clock is low.
00149      */
00150     cnt = 0;
00151     clkOut.input();
00152     while (clkOut.read() == 0) {
00153         cnt++;
00154         if (MAX_RETRY < cnt) {
00155             return false;
00156         }
00157         wait_us(1);
00158     }
00159     return true;
00160 }
00161 
00162 /**
00163  * Wait a clock down edge.
00164  *
00165  * @return true if wait done.
00166  */
00167 
00168 bool PS2MS::waitClockDownEdge(void)
00169 {
00170     //tot.reset();
00171     //tot.start();
00172     //while (work.cStart == work.cEnd) {
00173     //    if (tot.read_ms() > CLOCK_DOWN_EDGE_WAIT_MS) {
00174     //        tot.stop();
00175     //        return false;
00176     //    }
00177     //}
00178     //tot.stop();
00179 
00180     // char c = work.buffer[work.cStart++];
00181     //work.cStart =  work.cStart % RINGBUFSIZ;
00182 
00183     //return c;
00184     int cnt;
00185     /*
00186      * Wait until clock is low.
00187      */
00188     cnt = 0;
00189     clkOut.input();
00190     while (clkOut.read() == 0) {
00191         cnt++;
00192         if (MAX_RETRY < cnt) {
00193             return false;
00194         }
00195         wait_us(1);
00196     }
00197     /*
00198      * Wait until clock is high.
00199      */
00200     cnt = 0;
00201     while (clkOut.read() == 1) {
00202         cnt++;
00203         if (MAX_RETRY < cnt) {
00204             return false;
00205         }
00206         wait_us(1);
00207     }
00208     return true;
00209 }
00210 
00211 /**
00212  * Set timeout.
00213  *
00214  * @param ms Timeout ms.
00215  */
00216 void PS2MS::setTimeout(int ms)
00217 {
00218     timeout = ms;
00219 }
00220 
00221 void PS2MS::func_timeout(void)
00222 {
00223     work.bitcnt = 0;
00224 }
00225 
00226 void PS2MS::func_fall(void)
00227 {
00228     if (mSending) {
00229         return;
00230     }
00231     mInFuncFall = true;
00232     int oddpar = 0;
00233 
00234     /*
00235      */
00236     switch (work.bitcnt) {
00237         case 0:
00238             /*
00239              * Start bit.
00240              */
00241             int res = dat.read();
00242             if (res != 0) {
00243                 //printf("Illegal start bit condition. %d\n\r" + res);
00244             }
00245             work.bitcnt++;
00246             break;
00247         case 9:
00248             /*
00249              * Parity bit.
00250              */
00251             for (int i = 0; i < 8; i++) {
00252                 if ((work.buffer[work.cEnd] & (1 << i)) != 0) {
00253                     oddpar++;
00254                 }
00255             }
00256             if (dat.read() == 1) {
00257                 oddpar++;
00258             }
00259             if ((oddpar % 2) != 1) {
00260                 //printf("Data parity error.\n");
00261             }
00262             work.bitcnt++;
00263             break;
00264         case 10:
00265             /*
00266              * Stop bit.
00267              */
00268             if (dat.read() != 1) {
00269                 //printf("Illegal stop bit condition.\n");
00270             }
00271             if (work.cStart != ((work.cEnd + 1) % RINGBUFSIZ)) {
00272                 work.cEnd++;
00273                 work.cEnd = work.cEnd % RINGBUFSIZ;
00274                 work.bitcnt = 0;
00275             } else {
00276                 init_work();
00277                 printf("Buffer overrun.\n");
00278             }
00279             break;
00280         default:
00281             if ((1 <= work.bitcnt) && (work.bitcnt <= 8)) {
00282                 /*
00283                  * data bit.
00284                  */
00285                 if (dat.read() == 1) {
00286                     work.buffer[work.cEnd] |= (1 << (work.bitcnt - 1));
00287                 } else {
00288                     work.buffer[work.cEnd] &= ~(1 << (work.bitcnt - 1));
00289                 }
00290                 work.bitcnt++;
00291             } else {
00292                 /*
00293                  * Illegal internal state.
00294                  */
00295                 //printf("Illegal internal state found.\n");
00296                 init_work();
00297             }
00298             break;
00299     }
00300     wdt.detach();
00301     wdt.attach_us(this, &PS2MS::func_timeout, 250);
00302     mInFuncFall = false;
00303 }
00304 
00305 void PS2MS::init_work(void)
00306 {
00307     work.bitcnt = 0;
00308     work.cStart = 0;
00309     work.cEnd = 0;
00310 }