Kiibohd Controller
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
Это архивный репозиторий. Вы можете его клонировать или просматривать файлы, но не вносить изменения или открывать задачи/запросы на слияние.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /*
  2. * Copyright (C) 2014 Jan Rychter
  3. * Modifications (C) 2015-2016 Jacob Alexander
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files ( the "Software" ), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in all
  13. * copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. * SOFTWARE.
  22. */
  23. // ----- Includes ----
  24. // Compiler Includes
  25. #include <Lib/ScanLib.h>
  26. // Project Includes
  27. #include <print.h>
  28. #include <kll_defs.h>
  29. // Local Includes
  30. #include "i2c.h"
  31. // ----- Variables -----
  32. volatile I2C_Channel i2c_channels[ISSI_I2C_Buses_define];
  33. uint32_t i2c_offset[] = {
  34. 0x0, // Bus 0
  35. 0x1000, // Bus 1
  36. };
  37. // ----- Functions -----
  38. inline void i2c_setup()
  39. {
  40. for ( uint8_t ch = 0; ch < ISSI_I2C_Buses_define; ch++ )
  41. {
  42. volatile uint8_t *I2C_F = (uint8_t*)(&I2C0_F) + i2c_offset[ch];
  43. volatile uint8_t *I2C_FLT = (uint8_t*)(&I2C0_FLT) + i2c_offset[ch];
  44. volatile uint8_t *I2C_C1 = (uint8_t*)(&I2C0_C1) + i2c_offset[ch];
  45. volatile uint8_t *I2C_C2 = (uint8_t*)(&I2C0_C2) + i2c_offset[ch];
  46. switch ( ch )
  47. {
  48. case 0:
  49. // Enable I2C internal clock
  50. SIM_SCGC4 |= SIM_SCGC4_I2C0; // Bus 0
  51. // External pull-up resistor
  52. PORTB_PCR0 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2);
  53. PORTB_PCR1 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2);
  54. break;
  55. case 1:
  56. // Enable I2C internal clock
  57. SIM_SCGC4 |= SIM_SCGC4_I2C1; // Bus 1
  58. // External pull-up resistor
  59. PORTC_PCR10 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2);
  60. PORTC_PCR11 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2);
  61. break;
  62. }
  63. // SCL Frequency Divider
  64. // 1.8 MBaud ( likely higher than spec )
  65. // 0x82 -> 36 MHz / (4 * 3) = 2.25 MBaud
  66. // 0x80 => mul(4)
  67. // 0x05 => ICL(5)
  68. *I2C_F = 0x84;
  69. *I2C_FLT = 4;
  70. *I2C_C1 = I2C_C1_IICEN;
  71. *I2C_C2 = I2C_C2_HDRS; // High drive select
  72. switch ( ch )
  73. {
  74. case 0:
  75. // Enable I2C Interrupt
  76. NVIC_ENABLE_IRQ( IRQ_I2C0 );
  77. break;
  78. case 1:
  79. // Enable I2C Interrupt
  80. NVIC_ENABLE_IRQ( IRQ_I2C1 );
  81. break;
  82. }
  83. }
  84. }
  85. uint8_t i2c_busy( uint8_t ch )
  86. {
  87. volatile I2C_Channel *channel = &( i2c_channels[ch] );
  88. if ( channel->status == I2C_BUSY )
  89. {
  90. return 1;
  91. }
  92. return 0;
  93. }
  94. uint8_t i2c_any_busy()
  95. {
  96. for ( uint8_t ch = 0; ch < ISSI_I2C_Buses_define; ch++ )
  97. {
  98. if ( i2c_busy( ch ) )
  99. return 1;
  100. }
  101. return 0;
  102. }
  103. // These are here for readability and correspond to bit 0 of the address byte.
  104. #define I2C_WRITING 0
  105. #define I2C_READING 1
  106. int32_t i2c_send_sequence(
  107. uint8_t ch,
  108. uint16_t *sequence,
  109. uint32_t sequence_length,
  110. uint8_t *received_data,
  111. void ( *callback_fn )( void* ),
  112. void *user_data
  113. ) {
  114. volatile I2C_Channel *channel = &( i2c_channels[ch] );
  115. volatile uint8_t *I2C_C1 = (uint8_t*)(&I2C0_C1) + i2c_offset[ch];
  116. volatile uint8_t *I2C_S = (uint8_t*)(&I2C0_S) + i2c_offset[ch];
  117. volatile uint8_t *I2C_D = (uint8_t*)(&I2C0_D) + i2c_offset[ch];
  118. int32_t result = 0;
  119. uint8_t status;
  120. if ( channel->status == I2C_BUSY )
  121. {
  122. return -1;
  123. }
  124. // Debug
  125. /*
  126. for ( uint8_t c = 0; c < sequence_length; c++ )
  127. {
  128. printHex( sequence[c] );
  129. print(" ");
  130. }
  131. print(NL);
  132. */
  133. channel->sequence = sequence;
  134. channel->sequence_end = sequence + sequence_length;
  135. channel->received_data = received_data;
  136. channel->status = I2C_BUSY;
  137. channel->txrx = I2C_WRITING;
  138. channel->callback_fn = callback_fn;
  139. channel->user_data = user_data;
  140. // reads_ahead does not need to be initialized
  141. // Acknowledge the interrupt request, just in case
  142. *I2C_S |= I2C_S_IICIF;
  143. *I2C_C1 = ( I2C_C1_IICEN | I2C_C1_IICIE );
  144. // Generate a start condition and prepare for transmitting.
  145. *I2C_C1 |= ( I2C_C1_MST | I2C_C1_TX );
  146. status = *I2C_S;
  147. if ( status & I2C_S_ARBL )
  148. {
  149. warn_print("Arbitration lost");
  150. result = -1;
  151. goto i2c_send_sequence_cleanup;
  152. }
  153. // Write the first (address) byte.
  154. *I2C_D = *channel->sequence++;
  155. // Everything is OK.
  156. return result;
  157. i2c_send_sequence_cleanup:
  158. *I2C_C1 &= ~( I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TX );
  159. channel->status = I2C_ERROR;
  160. return result;
  161. }
  162. void i2c_isr( uint8_t ch )
  163. {
  164. volatile I2C_Channel* channel = &i2c_channels[ch];
  165. volatile uint8_t *I2C_C1 = (uint8_t*)(&I2C0_C1) + i2c_offset[ch];
  166. volatile uint8_t *I2C_S = (uint8_t*)(&I2C0_S) + i2c_offset[ch];
  167. volatile uint8_t *I2C_D = (uint8_t*)(&I2C0_D) + i2c_offset[ch];
  168. uint8_t element;
  169. uint8_t status;
  170. status = *I2C_S;
  171. // Acknowledge the interrupt request
  172. *I2C_S |= I2C_S_IICIF;
  173. // Arbitration problem
  174. if ( status & I2C_S_ARBL )
  175. {
  176. warn_msg("Arbitration error. Bus: ");
  177. printHex( ch );
  178. print(NL);
  179. *I2C_S |= I2C_S_ARBL;
  180. goto i2c_isr_error;
  181. }
  182. if ( channel->txrx == I2C_READING )
  183. {
  184. switch( channel->reads_ahead )
  185. {
  186. // All the reads in the sequence have been processed ( but note that the final data register read still needs to
  187. // be done below! Now, the next thing is either a restart or the end of a sequence. In any case, we need to
  188. // switch to TX mode, either to generate a repeated start condition, or to avoid triggering another I2C read
  189. // when reading the contents of the data register.
  190. case 0:
  191. *I2C_C1 |= I2C_C1_TX;
  192. // Perform the final data register read now that it's safe to do so.
  193. *channel->received_data++ = *I2C_D;
  194. // Do we have a repeated start?
  195. if ( ( channel->sequence < channel->sequence_end ) && ( *channel->sequence == I2C_RESTART ) )
  196. {
  197. // Generate a repeated start condition.
  198. *I2C_C1 |= I2C_C1_RSTA;
  199. // A restart is processed immediately, so we need to get a new element from our sequence. This is safe, because
  200. // a sequence cannot end with a RESTART: there has to be something after it. Note that the only thing that can
  201. // come after a restart is an address write.
  202. channel->txrx = I2C_WRITING;
  203. channel->sequence++;
  204. element = *channel->sequence;
  205. *I2C_D = element;
  206. }
  207. else
  208. {
  209. goto i2c_isr_stop;
  210. }
  211. break;
  212. case 1:
  213. // do not ACK the final read
  214. *I2C_C1 |= I2C_C1_TXAK;
  215. *channel->received_data++ = *I2C_D;
  216. break;
  217. default:
  218. *channel->received_data++ = *I2C_D;
  219. break;
  220. }
  221. channel->reads_ahead--;
  222. }
  223. // channel->txrx == I2C_WRITING
  224. else
  225. {
  226. // First, check if we are at the end of a sequence.
  227. if ( channel->sequence == channel->sequence_end )
  228. goto i2c_isr_stop;
  229. // We received a NACK. Generate a STOP condition and abort.
  230. if ( status & I2C_S_RXAK )
  231. {
  232. warn_print("NACK Received");
  233. goto i2c_isr_error;
  234. }
  235. // check next thing in our sequence
  236. element = *channel->sequence;
  237. // Do we have a restart? If so, generate repeated start and make sure TX is on.
  238. if ( element == I2C_RESTART )
  239. {
  240. *I2C_C1 |= I2C_C1_RSTA | I2C_C1_TX;
  241. // A restart is processed immediately, so we need to get a new element from our sequence.
  242. // This is safe, because a sequence cannot end with a RESTART: there has to be something after it.
  243. channel->sequence++;
  244. element = *channel->sequence;
  245. // Note that the only thing that can come after a restart is a write.
  246. *I2C_D = element;
  247. }
  248. else
  249. {
  250. if ( element == I2C_READ ) {
  251. channel->txrx = I2C_READING;
  252. // How many reads do we have ahead of us ( not including this one )?
  253. // For reads we need to know the segment length to correctly plan NACK transmissions.
  254. // We already know about one read
  255. channel->reads_ahead = 1;
  256. while (
  257. ( ( channel->sequence + channel->reads_ahead ) < channel->sequence_end ) &&
  258. ( *( channel->sequence + channel->reads_ahead ) == I2C_READ )
  259. ) {
  260. channel->reads_ahead++;
  261. }
  262. // Switch to RX mode.
  263. *I2C_C1 &= ~I2C_C1_TX;
  264. // do not ACK the final read
  265. if ( channel->reads_ahead == 1 )
  266. {
  267. *I2C_C1 |= I2C_C1_TXAK;
  268. }
  269. // ACK all but the final read
  270. else
  271. {
  272. *I2C_C1 &= ~( I2C_C1_TXAK );
  273. }
  274. // Dummy read comes first, note that this is not valid data!
  275. // This only triggers a read, actual data will come in the next interrupt call and overwrite this.
  276. // This is why we do not increment the received_data pointer.
  277. *channel->received_data = *I2C_D;
  278. channel->reads_ahead--;
  279. }
  280. // Not a restart, not a read, must be a write.
  281. else
  282. {
  283. *I2C_D = element;
  284. }
  285. }
  286. }
  287. channel->sequence++;
  288. return;
  289. i2c_isr_stop:
  290. // Generate STOP ( set MST=0 ), switch to RX mode, and disable further interrupts.
  291. *I2C_C1 &= ~( I2C_C1_MST | I2C_C1_IICIE | I2C_C1_TXAK );
  292. channel->status = I2C_AVAILABLE;
  293. // Call the user-supplied callback function upon successful completion (if it exists).
  294. if ( channel->callback_fn )
  295. {
  296. // Delay 10 microseconds before starting linked function
  297. // TODO, is this chip dependent? -HaaTa
  298. delayMicroseconds(10);
  299. ( *channel->callback_fn )( channel->user_data );
  300. }
  301. return;
  302. i2c_isr_error:
  303. // Generate STOP and disable further interrupts.
  304. *I2C_C1 &= ~( I2C_C1_MST | I2C_C1_IICIE );
  305. channel->status = I2C_ERROR;
  306. return;
  307. }
  308. void i2c0_isr()
  309. {
  310. i2c_isr( 0 );
  311. }
  312. void i2c1_isr()
  313. {
  314. i2c_isr( 1 );
  315. }