Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Wed Jul 13 2022 15:37:35 by
1.7.2