Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

785 lines
24 KiB

  1. // $Header: G:/SwDev/WDM/Video/bt848/rcs/I2c.cpp 1.6 1998/05/08 18:18:52 tomz Exp $
  2. //===========================================================================
  3. // I2C DATA/CONTROL REGISTER API
  4. //===========================================================================
  5. #include "bti2c.h"
  6. //**************************************************************************
  7. // DEFINES
  8. //**************************************************************************
  9. #define I2C_WRITE 0 // write operation
  10. #define I2C_READ 1 // read operation
  11. #define PCI_FREQ 33000000L // frequency for PCI in hz
  12. #define I2CDIV_MAX 15 // I2C maximum divider
  13. #define TIMEOUT 500 // timeout value (500ms) to wait for an I2C operation
  14. // passing 3 values to I2C takes ~450ms
  15. #ifdef HAUPPAUGEI2CPROVIDER
  16. extern "C" ULONG GetTickCount( void );
  17. #endif
  18. // Let me know at compile time what i2c setup I'm building
  19. #if SHOW_BUILD_MSGS
  20. #ifdef HAUPPAUGEI2CPROVIDER
  21. #pragma message("*** using 'Hauppauge' i2c code")
  22. #else
  23. #pragma message("*** not using 'Hauppauge' i2c code")
  24. #endif
  25. #ifdef HARDWAREI2C
  26. #pragma message("*** using hardware i2c code")
  27. #else
  28. #pragma message("*** not using hardware i2c code")
  29. #endif
  30. #endif
  31. //===========================================================================
  32. // Bt848 I2C Class Implementation
  33. //===========================================================================
  34. /////////////////////////////////////////////////////////////////////////////
  35. // Constructor
  36. /////////////////////////////////////////////////////////////////////////////
  37. I2C::I2C( void ) :
  38. // construct I2C register and register fields
  39. decRegINT_STAT ( 0x100, RW ), // Interrupt Status register
  40. decFieldI2CDONE( decRegINT_STAT, 8, 1, RR ),
  41. decFieldRACK( decRegINT_STAT, 25, 1, RO ),
  42. decRegI2C ( 0x110, RW ), // I2C Data/Control register
  43. decFieldI2CDB0( decRegI2C, 24, 8, RW ),
  44. decFieldI2CDB1( decRegI2C, 16, 8, RW ),
  45. decFieldI2CDB2( decRegI2C, 8, 8, RW ),
  46. decFieldI2CDIV( decRegI2C, 4, 4, RW),
  47. decFieldSYNC( decRegI2C, 3, 1, RW),
  48. decFieldW3B( decRegI2C, 2, 1, RW),
  49. decFieldSCL( decRegI2C, 1, 1, RW),
  50. decFieldSDA( decRegI2C, 0, 1, RW)
  51. {
  52. initOK = false;
  53. cycle = 0L;
  54. errNum = I2CERR_OK;
  55. mode = I2CMode_None;
  56. }
  57. /////////////////////////////////////////////////////////////////////////////
  58. // Destructor
  59. /////////////////////////////////////////////////////////////////////////////
  60. I2C::~I2C()
  61. {
  62. }
  63. /////////////////////////////////////////////////////////////////////////////
  64. // Method: bool I2C::IsInitOK( void )
  65. // Purpose: Check if I2C is initialized successfully
  66. // Input: None
  67. // Output: None
  68. // Return: true or false
  69. /////////////////////////////////////////////////////////////////////////////
  70. bool I2C::IsInitOK( void )
  71. {
  72. // initialize I2C register shadow
  73. I2CResetShadow();
  74. initOK = true;
  75. return( initOK );
  76. }
  77. #ifdef HARDWAREI2C
  78. /////////////////////////////////////////////////////////////////////////////
  79. // Method: ErrorCode I2C::I2CInitHWMode( long freq )
  80. // Purpose: Initialize I2C for hardware control of SCL and SDA
  81. // Input: long freq - frequency (hz) to run SCL at
  82. // Output: None
  83. // Return: None
  84. /////////////////////////////////////////////////////////////////////////////
  85. ErrorCode I2C::I2CInitHWMode( long freq )
  86. {
  87. // initialization was successful?
  88. if ( initOK != true )
  89. {
  90. errNum = I2CERR_INIT;
  91. return Fail;
  92. }
  93. // initialize I2C register shadow
  94. I2CResetShadow();
  95. decFieldSCL = sh.i2cShadow.scl = 1; // must be 1 for hardware mode
  96. decFieldSDA = sh.i2cShadow.sda = 1; // must be 1 for hardware mode
  97. I2CSetFreq( freq ); // set frequency for hardware control
  98. // I2C is running hardware mode
  99. mode = I2CMode_HW;
  100. return Success;
  101. }
  102. #endif
  103. /////////////////////////////////////////////////////////////////////////////
  104. // Method: void I2C::I2CSetFreq( long freq )
  105. // Purpose: Set frequency for SCL
  106. // Input: long freq - frequency (hz) to run SCL at. (137.5khz to 2.0625Mhz)
  107. // PCI frequency 33Mhz: SCL = (412.50Khz to 33.81Khz)
  108. // 25Mhz: SCL = (312.50Khz to 25.61Khz)
  109. // Output: None
  110. // Return: None
  111. /////////////////////////////////////////////////////////////////////////////
  112. void I2C::I2CSetFreq( long freq )
  113. {
  114. unsigned int i2cdiv;
  115. // avoid division errors
  116. if( freq > 1 )
  117. i2cdiv = (unsigned int) (PCI_FREQ / (64 * freq));
  118. else
  119. i2cdiv = 0;
  120. if( i2cdiv > I2CDIV_MAX )
  121. i2cdiv = I2CDIV_MAX;
  122. decFieldI2CDIV = sh.i2cShadow.div = i2cdiv;
  123. }
  124. #ifdef HARDWAREI2C
  125. /////////////////////////////////////////////////////////////////////////////
  126. // Method: int I2C::I2CReadDiv( void )
  127. // Purpose: Obtain value of programmable divider
  128. // Input: None
  129. // Output: None
  130. // Return: Value of programmable divider
  131. /////////////////////////////////////////////////////////////////////////////
  132. int I2C::I2CReadDiv( void )
  133. {
  134. return decFieldI2CDIV;
  135. }
  136. /////////////////////////////////////////////////////////////////////////////
  137. // Method: ErrorCode I2C::I2CHWRead( BYTE address, BYTE *value )
  138. // Purpose: Perform a hardware read from the I2C
  139. // Input: int address - address to be read from
  140. // Output: int *value - retrieved value
  141. // Return: Success or Fail
  142. /////////////////////////////////////////////////////////////////////////////
  143. ErrorCode I2C::I2CHWRead( BYTE address, BYTE *value )
  144. {
  145. // check if correct mode is selected
  146. if ( mode != I2CMode_HW )
  147. {
  148. errNum = I2CERR_MODE;
  149. return Fail;
  150. }
  151. shadow::_i2c_reg i2cTemp = sh.i2cShadow; // obtain previous settings that didn't change
  152. // see above for reasons of doing all these.
  153. i2cTemp.addr_rw = address | I2C_READ;
  154. i2cTemp.byte1 = 0;
  155. i2cTemp.byte2 = 0;
  156. i2cTemp.w3b = 0;
  157. decRegI2C = *(DWORD *)&i2cTemp;
  158. if ( I2CHWWaitUntilDone( TIMEOUT ) == Fail )
  159. {
  160. errNum = I2CERR_TIMEOUT;
  161. return Fail;
  162. }
  163. *value = (BYTE) decFieldI2CDB2; // returned value is in 3rd byte
  164. if ( I2CHWReceivedACK() == true )
  165. return Success;
  166. else
  167. {
  168. errNum = I2CERR_NOACK;
  169. return Fail;
  170. }
  171. }
  172. /////////////////////////////////////////////////////////////////////////////
  173. // Method: ErrorCode I2C::I2CHWWrite2( BYTE address, BYTE value1 )
  174. // Purpose: Perform a hardware write of two bytes to the I2C
  175. // Input: int address - address to be written to
  176. // int value1 - value of 2nd byte to be written
  177. // Output: None
  178. // Return: Success or Fail
  179. /////////////////////////////////////////////////////////////////////////////
  180. ErrorCode I2C::I2CHWWrite2( BYTE address, BYTE value1 )
  181. {
  182. // check if correct mode is selected
  183. if ( mode != I2CMode_HW )
  184. {
  185. errNum = I2CERR_MODE;
  186. return Fail;
  187. }
  188. shadow::_i2c_reg i2cTemp = sh.i2cShadow; // obtain previous settings that didn't change
  189. // see above for reasons of doing all these.
  190. i2cTemp.addr_rw = address | I2C_WRITE;
  191. i2cTemp.byte1 = value1;
  192. i2cTemp.byte2 = 0;
  193. i2cTemp.w3b = 0;
  194. decRegI2C = *(DWORD *)&i2cTemp;
  195. if ( I2CHWWaitUntilDone( TIMEOUT ) == Fail )
  196. {
  197. errNum = I2CERR_TIMEOUT;
  198. return Fail;
  199. }
  200. if ( I2CHWReceivedACK() == true )
  201. return Success;
  202. else
  203. {
  204. errNum = I2CERR_NOACK;
  205. return Fail;
  206. }
  207. }
  208. /////////////////////////////////////////////////////////////////////////////
  209. // Method: ErrorCode I2C::I2CHWWrite3( BYTE address, BYTE value1, BYTE value2 )
  210. // Purpose: Perform a hardware write of three bytes to the I2C
  211. // Input: int address - address to be written to
  212. // int value1 - value of 2nd byte to be written
  213. // int value2 - value of 3rd byte to be written
  214. // Output: None
  215. // Return: Success or Fail
  216. /////////////////////////////////////////////////////////////////////////////
  217. ErrorCode I2C::I2CHWWrite3( BYTE address, BYTE value1, BYTE value2 )
  218. {
  219. // check if correct mode is selected
  220. if ( mode != I2CMode_HW )
  221. {
  222. errNum = I2CERR_MODE;
  223. return Fail;
  224. }
  225. shadow::_i2c_reg i2cTemp = sh.i2cShadow; // obtain previous settings that didn't change
  226. // see above for reasons of doing all these.
  227. i2cTemp.addr_rw = address | I2C_WRITE;
  228. i2cTemp.byte1 = value1;
  229. i2cTemp.byte2 = value2;
  230. i2cTemp.w3b = 1;
  231. decRegI2C = *(DWORD *)&i2cTemp;
  232. if ( I2CHWWaitUntilDone( TIMEOUT ) == Fail )
  233. {
  234. errNum = I2CERR_TIMEOUT;
  235. return Fail;
  236. }
  237. if ( I2CHWReceivedACK() == true )
  238. return Success;
  239. else
  240. {
  241. errNum = I2CERR_NOACK;
  242. return Fail;
  243. }
  244. }
  245. /////////////////////////////////////////////////////////////////////////////
  246. // Method: int I2C::I2CReadSync( void )
  247. // Purpose: Read I2C sync value
  248. // Input: None
  249. // Output: None
  250. // Return: Sync value
  251. /////////////////////////////////////////////////////////////////////////////
  252. int I2C::I2CReadSync( void )
  253. {
  254. return decFieldSYNC;
  255. }
  256. #endif
  257. /////////////////////////////////////////////////////////////////////////////
  258. // Method: int I2C::I2CGetLastError( void )
  259. // Purpose: Obtain last I2C error number
  260. // Input: None
  261. // Output: None
  262. // Return: Last I2C error number
  263. /////////////////////////////////////////////////////////////////////////////
  264. int I2C::I2CGetLastError( void )
  265. {
  266. return errNum;
  267. }
  268. //============================================================================
  269. // Following functions are used internally
  270. //============================================================================
  271. /////////////////////////////////////////////////////////////////////////////
  272. // Method: void I2C::I2CResetShadow( void )
  273. // Purpose: Reset register shadow
  274. // Input: int maxWait - maximum waiting time in milliseconds
  275. // Output: None
  276. // Return: Success if done; Fail if timeout
  277. /////////////////////////////////////////////////////////////////////////////
  278. void I2C::I2CResetShadow( void )
  279. {
  280. // initialize I2C register shadow
  281. sh.Initer = 0;
  282. }
  283. /////////////////////////////////////////////////////////////////////////////
  284. // Method: ErrorCode I2C::I2CHWWaitUntilDone( int maxWait )
  285. // Purpose: Wait for hardware I2C to finish
  286. // Input: int maxWait - maximum waiting time in milliseconds
  287. // Output: None
  288. // Return: Success if done; Fail if timeout
  289. /////////////////////////////////////////////////////////////////////////////
  290. ErrorCode I2C::I2CHWWaitUntilDone( int maxWait )
  291. {
  292. // DWORD startTime = GetTickCount();
  293. // loop until either I2CDONE is set or timeout
  294. while (1)
  295. {
  296. if ( I2CHWIsDone() == true )
  297. return Success;
  298. #if 0
  299. // timeout?
  300. if ( GetTickCount() - startTime > (DWORD)maxWait )
  301. {
  302. errNum = I2CERR_TIMEOUT;
  303. return Fail;
  304. }
  305. #endif
  306. }
  307. }
  308. /////////////////////////////////////////////////////////////////////////////
  309. // Method: bool I2C::I2CHWIsDone( void )
  310. // Purpose: Determine if I2C has finished a read or write operation by
  311. // checking the I2CDONE bit in the interrupt status register
  312. // Input: None
  313. // Output: None
  314. // Return: true if done; else false
  315. /////////////////////////////////////////////////////////////////////////////
  316. bool I2C::I2CHWIsDone( void )
  317. {
  318. if ( decFieldI2CDONE != 0 )
  319. {
  320. // Need to clear the bit when it is set; don't want to alter any other bits
  321. // Writing a 1 to the bit clears it.
  322. decFieldI2CDONE = 1;
  323. return true;
  324. }
  325. else
  326. return false;
  327. }
  328. /////////////////////////////////////////////////////////////////////////////
  329. // Method: bool I2C::I2CHWReceivedACK( void )
  330. // Purpose: Determine if ACK is receieved
  331. // Input: None
  332. // Output: None
  333. // Return: true if ACK received; else false
  334. /////////////////////////////////////////////////////////////////////////////
  335. bool I2C::I2CHWReceivedACK( void )
  336. {
  337. return ( ( decFieldRACK != 0 ) ? true : false );
  338. }
  339. #ifdef HAUPPAUGEI2CPROVIDER
  340. /////////////////////////////////////////////////////////////////////////////
  341. // Method: ErrorCode I2C::I2CInitSWMode( long freq )
  342. // Purpose: Initialize I2C for software control of SCL and SDA
  343. // Input: long freq - frequency (hz) to run SCL at
  344. // Output: None
  345. // Return: None
  346. // Note: After calling I2CIsInitOK(), application should call this
  347. // function and check for return value is Success before starting
  348. // software communication.
  349. /////////////////////////////////////////////////////////////////////////////
  350. ErrorCode I2C::I2CInitSWMode( long freq )
  351. {
  352. // initialization was successful?
  353. if ( initOK != true )
  354. {
  355. errNum = I2CERR_INIT;
  356. return Fail;
  357. }
  358. // initialize I2C register shadow
  359. I2CResetShadow();
  360. decFieldSCL = sh.i2cShadow.scl = 1;
  361. decFieldSDA = sh.i2cShadow.sda = 1;
  362. I2CSetFreq( 0 ); // set frequency to 0 for software control
  363. // need to calibrate in order to generate the correct clock cycle
  364. // the approach is to calculate how many dummy loop we need in order to
  365. // generate a cycle that is 2 * freq * 1000 Hz
  366. cycle = 10000L; // use a large number to start
  367. DWORD elapsed = 0L;
  368. while ( elapsed < 5 ) // loop until delay is long enough for calculation
  369. {
  370. cycle *= 10;
  371. DWORD start = GetTickCount();
  372. for ( volatile DWORD i = cycle; i > 0; i-- )
  373. ;
  374. elapsed = GetTickCount() - start;
  375. }
  376. if ( freq > 1 )
  377. cycle = cycle / elapsed * 1000L / freq / 2;
  378. // I2C is running software mode
  379. mode = I2CMode_SW;
  380. return Success;
  381. }
  382. /////////////////////////////////////////////////////////////////////////////
  383. // Method: ErrorCode I2C::I2CSWStart( void )
  384. // Purpose: Generate START condition using software control
  385. // Input: None
  386. // Output: None
  387. // Return: Success or Fail
  388. /////////////////////////////////////////////////////////////////////////////
  389. ErrorCode I2C::I2CSWStart( void )
  390. {
  391. // check if correct mode is selected
  392. if ( mode != I2CMode_SW )
  393. {
  394. errNum = I2CERR_MODE;
  395. return Fail;
  396. }
  397. // SendStart - send an I2c start
  398. // i.e. SDA 1 -> 0 with SCL = 1
  399. if ( I2CSWSetSDA( LevelHi ) != Success ) { errNum = I2CERR_SDA; return Fail; }
  400. if ( I2CSWSetSCL( LevelHi ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  401. if ( I2CSWSetSDA( LevelLow ) != Success ) { errNum = I2CERR_SDA; return Fail; }
  402. if ( I2CSWSetSCL( LevelLow ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  403. return Success;
  404. }
  405. /////////////////////////////////////////////////////////////////////////////
  406. // Method: ErrorCode I2C::I2CSWStop( void )
  407. // Purpose: Generate STOP condition using software control
  408. // Input: None
  409. // Output: None
  410. // Return: Success or Fail
  411. /////////////////////////////////////////////////////////////////////////////
  412. ErrorCode I2C::I2CSWStop( void )
  413. {
  414. // check if correct mode is selected
  415. if ( mode != I2CMode_SW )
  416. {
  417. errNum = I2CERR_MODE;
  418. return Fail;
  419. }
  420. // SendStop - sends an I2C stop, releasing the bus.
  421. // i.e. SDA 0 -> 1 with SCL = 1
  422. if ( I2CSWSetSCL( LevelLow ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  423. if ( I2CSWSetSDA( LevelLow ) != Success ) { errNum = I2CERR_SDA; return Fail; }
  424. if ( I2CSWSetSCL( LevelHi ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  425. if ( I2CSWSetSDA( LevelHi ) != Success ) { errNum = I2CERR_SDA; return Fail; }
  426. return Success;
  427. }
  428. /////////////////////////////////////////////////////////////////////////////
  429. // Method: ErrorCode I2C::I2CSWRead( BYTE * value )
  430. // Purpose: Read a byte from the slave
  431. // Input: None
  432. // Output: BYTE * value - byte read from slave
  433. // Return: Success or Fail
  434. /////////////////////////////////////////////////////////////////////////////
  435. ErrorCode I2C::I2CSWRead( BYTE * value )
  436. {
  437. // check if correct mode is selected
  438. if ( mode != I2CMode_SW )
  439. {
  440. errNum = I2CERR_MODE;
  441. return Fail;
  442. }
  443. *value = 0x00;
  444. // read 8 bits from I2c into Accumulator
  445. for( BYTE mask = 0x80; mask > 0; mask = (BYTE)( mask >> 1 ) )
  446. {
  447. if ( I2CSWSetSCL( LevelLow ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  448. if ( I2CSWSetSCL( LevelHi ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  449. if ( I2CSWReadSDA() == TRUE )
  450. *value = (BYTE)( *value | mask ); // set the bit
  451. }
  452. return Success;
  453. }
  454. /////////////////////////////////////////////////////////////////////////////
  455. // Method: ErrorCode I2C::I2CSWWrite( BYTE value )
  456. // Purpose: Write a byte to the slave
  457. // Input: BYTE value - byte to be written to slave
  458. // Output: None
  459. // Return: Success or Fail
  460. /////////////////////////////////////////////////////////////////////////////
  461. ErrorCode I2C::I2CSWWrite( BYTE value )
  462. {
  463. // check if correct mode is selected
  464. if ( mode != I2CMode_SW )
  465. {
  466. errNum = I2CERR_MODE;
  467. return Fail;
  468. }
  469. // generate bit patterns by setting SCL and SDA lines
  470. for ( BYTE mask = 0x80; mask > 0; mask = (BYTE)(mask >> 1) )
  471. {
  472. if ( I2CSWSetSCL( LevelLow ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  473. // Send one data bit.
  474. if ( value & mask ) // Put data bit on pin.
  475. {
  476. if ( I2CSWSetSDA( LevelHi ) != Success ) { errNum = I2CERR_SDA; return Fail; }
  477. }
  478. else
  479. {
  480. if ( I2CSWSetSDA( LevelLow ) != Success ) { errNum = I2CERR_SDA; return Fail; }
  481. }
  482. if ( I2CSWSetSCL( LevelHi ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  483. }
  484. return I2CSWWaitForACK();
  485. }
  486. /////////////////////////////////////////////////////////////////////////////
  487. // Method: ErrorCode I2C::I2CSWSendACK( void )
  488. // Purpose: Send ACK to slave
  489. // Input: None
  490. // Output: None
  491. // Return: Success or Fail
  492. /////////////////////////////////////////////////////////////////////////////
  493. ErrorCode I2C::I2CSWSendACK( void )
  494. {
  495. // check if correct mode is selected
  496. if ( mode != I2CMode_SW )
  497. {
  498. errNum = I2CERR_MODE;
  499. return Fail;
  500. }
  501. // Generate ACK signal
  502. // i.e. SDA = 0 with SCL = 1
  503. if ( I2CSWSetSCL( LevelLow ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  504. if ( I2CSWSetSDA( LevelLow ) != Success ) { errNum = I2CERR_SDA; return Fail; }
  505. if ( I2CSWSetSCL( LevelHi ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  506. if ( I2CSWSetSCL( LevelLow ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  507. if ( I2CSWSetSDA( LevelHi ) != Success ) { errNum = I2CERR_SDA; return Fail; }
  508. return Success;
  509. }
  510. /////////////////////////////////////////////////////////////////////////////
  511. // Method: ErrorCode I2C::I2CSWSendNACK( void )
  512. // Purpose: Send NACK to slave
  513. // Input: None
  514. // Output: None
  515. // Return: Success or Fail
  516. /////////////////////////////////////////////////////////////////////////////
  517. ErrorCode I2C::I2CSWSendNACK( void )
  518. {
  519. // check if correct mode is selected
  520. if ( mode != I2CMode_SW )
  521. {
  522. errNum = I2CERR_MODE;
  523. return Fail;
  524. }
  525. // Generate NACK signal
  526. // i.e. SDA = 1 with SCL = 1
  527. if ( I2CSWSetSCL( LevelLow ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  528. if ( I2CSWSetSDA( LevelHi ) != Success ) { errNum = I2CERR_SDA; return Fail; }
  529. if ( I2CSWSetSCL( LevelHi ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  530. if ( I2CSWSetSCL( LevelLow ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  531. if ( I2CSWSetSDA( LevelLow ) != Success ) { errNum = I2CERR_SDA; return Fail; }
  532. return Success;
  533. }
  534. /////////////////////////////////////////////////////////////////////////////
  535. // Method: ErrorCode I2C::I2CSWSetSCL( Level scl )
  536. // Purpose: Set software SCL value
  537. // Input: Level scl - Hi releases the SCL output; Low forces the SCL output low
  538. // Output: None
  539. // Return: Success or Fail
  540. /////////////////////////////////////////////////////////////////////////////
  541. ErrorCode I2C::I2CSWSetSCL( Level scl )
  542. {
  543. // check if correct mode is selected
  544. if ( mode != I2CMode_SW )
  545. {
  546. errNum = I2CERR_MODE;
  547. return Fail;
  548. }
  549. sh.i2cShadow.scl = scl;
  550. decRegI2C = *(DWORD *)&(sh.i2cShadow);
  551. // loop until SCL really changes or timeout
  552. DWORD maxWait = 500; // 500 mSec
  553. DWORD startTime = GetTickCount();
  554. while (1)
  555. {
  556. // has SCL changed yet?
  557. if ( I2CSWReadSCL() == scl )
  558. break;
  559. // timeout?
  560. if ( GetTickCount() - startTime > (DWORD)maxWait )
  561. {
  562. errNum = I2CERR_TIMEOUT;
  563. return Fail;
  564. }
  565. }
  566. I2CSWBitDelay();
  567. return Success;
  568. }
  569. /////////////////////////////////////////////////////////////////////////////
  570. // Method: int I2C::I2CSWReadSCL( void )
  571. // Purpose: Read software SCL value
  572. // Input: None
  573. // Output: None
  574. // Return: SCL value
  575. /////////////////////////////////////////////////////////////////////////////
  576. int I2C::I2CSWReadSCL( void )
  577. {
  578. return decFieldSCL;
  579. }
  580. /////////////////////////////////////////////////////////////////////////////
  581. // Method: ErrorCode I2C::I2CSWSetSDA( Level sda )
  582. // Purpose: Set software SDA value
  583. // Input: Level sda - Hi releases the SDA output; Low forces the SDA output low
  584. // Output: None
  585. // Return: Success or Fail
  586. /////////////////////////////////////////////////////////////////////////////
  587. ErrorCode I2C::I2CSWSetSDA( Level sda )
  588. {
  589. // check if correct mode is selected
  590. if ( mode != I2CMode_SW )
  591. {
  592. errNum = I2CERR_MODE;
  593. return Fail;
  594. }
  595. sh.i2cShadow.sda = sda;
  596. decRegI2C = *(DWORD *)&(sh.i2cShadow);
  597. I2CSWBitDelay();
  598. return Success;
  599. }
  600. /////////////////////////////////////////////////////////////////////////////
  601. // Method: int I2C::I2CSWReadSDA( void )
  602. // Purpose: Read software SDA value
  603. // Input: None
  604. // Output: None
  605. // Return: SDA value
  606. /////////////////////////////////////////////////////////////////////////////
  607. int I2C::I2CSWReadSDA( void )
  608. {
  609. return decFieldSDA;
  610. }
  611. /////////////////////////////////////////////////////////////////////////////
  612. // Method: void I2C::I2CSWBitDelay( void )
  613. // Purpose: Insures minimum high and low clock times on I2C bus.
  614. // Input: None
  615. // Output: None
  616. // Return: None
  617. // Note: This routine must be tuned for the desired frequency.
  618. /////////////////////////////////////////////////////////////////////////////
  619. void I2C::I2CSWBitDelay( void )
  620. {
  621. // unsigned int n;
  622. volatile DWORD i ;
  623. for ( i = cycle; i > 0; i-- )
  624. ;
  625. }
  626. /////////////////////////////////////////////////////////////////////////////
  627. // Method: ErrorCode I2C::I2CSWWaitForACK( void )
  628. // Purpose: Determine if ACK is receieved in software mode
  629. // Input: None
  630. // Output: None
  631. // Return: Success if ACK received; Fail if timeout
  632. /////////////////////////////////////////////////////////////////////////////
  633. ErrorCode I2C::I2CSWWaitForACK( void )
  634. {
  635. if ( I2CSWSetSCL( LevelLow ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  636. if ( I2CSWSetSDA( LevelHi ) != Success ) { errNum = I2CERR_SDA; return Fail; }
  637. // loop until either ACK or timeout
  638. DWORD maxWait = 500; // 500 mSec
  639. DWORD startTime = GetTickCount();
  640. while (1)
  641. {
  642. // SDA pin == 0 means the slave ACK'd
  643. if ( I2CSWReadSDA() == 0 )
  644. {
  645. if ( I2CSWSetSCL( LevelHi ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  646. if ( I2CSWSetSCL( LevelLow ) != Success ) { errNum = I2CERR_SCL; return Fail; }
  647. return Success;
  648. }
  649. // timeout?
  650. if ( GetTickCount() - startTime > (DWORD)maxWait )
  651. {
  652. if ( I2CSWStop() != Success ) return Fail;
  653. errNum = I2CERR_TIMEOUT;
  654. return Fail;
  655. }
  656. } // while
  657. }
  658. //
  659. // GetSystemTime in 100 nS units
  660. //
  661. ULONGLONG GetSystemTime()
  662. {
  663. ULONGLONG ticks;
  664. ULONGLONG rate;
  665. ticks = (ULONGLONG)KeQueryPerformanceCounter((PLARGE_INTEGER)&rate).QuadPart;
  666. //
  667. // convert from ticks to 100ns clock
  668. //
  669. ticks = (ticks & 0xFFFFFFFF00000000) / rate * 10000000 +
  670. (ticks & 0xFFFFFFFF) * 10000000 / rate;
  671. return(ticks);
  672. }
  673. extern "C" ULONG GetTickCount( void )
  674. {
  675. return (ULONG)( GetSystemTime() / 10000 );
  676. }
  677. #endif