gblink.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. // SPDX-License-Identifier: BSD-2-Clause
  2. // Copyright (c) 2023 KBEmbedded
  3. #include <furi.h>
  4. #include <furi_hal.h>
  5. #include <stm32wbxx_ll_exti.h>
  6. #include <stm32wbxx_ll_system.h>
  7. #include <stdint.h>
  8. #include <gblink/include/gblink.h>
  9. #include "exti_workaround_i.h"
  10. #include "clock_timer_i.h"
  11. struct gblink_pins {
  12. const GpioPin *serin;
  13. const GpioPin *serout;
  14. const GpioPin *clk;
  15. const GpioPin *sd;
  16. };
  17. const struct gblink_pins common_pinouts[PINOUT_COUNT] = {
  18. /* Original */
  19. {
  20. &gpio_ext_pc3,
  21. &gpio_ext_pb3,
  22. &gpio_ext_pb2,
  23. &gpio_ext_pa4,
  24. },
  25. /* MALVEKE EXT1 */
  26. {
  27. &gpio_ext_pa6,
  28. &gpio_ext_pa7,
  29. &gpio_ext_pb3,
  30. &gpio_ext_pa4,
  31. },
  32. };
  33. struct gblink {
  34. const GpioPin *serin;
  35. const GpioPin *serout;
  36. const GpioPin *clk;
  37. const GpioPin *sd;
  38. gblink_mode mode;
  39. void (*callback)(void* cb_context, uint8_t in);
  40. void *cb_context;
  41. /* These two semaphores serve similar but distinct purposes. */
  42. /* The transfer semaphore is taken as soon as a transfer() request
  43. * has been started. This is used in the function to wait until the
  44. * transfer has been completed.
  45. */
  46. FuriSemaphore *transfer_sem;
  47. /* The out byte semaphore is used to indicate that a byte transfer
  48. * is in progress. This is used in the transfer function to not allow
  49. * a transfer request if we're in the middle of sending a byte.
  50. * The transfer semaphore is not used for that purpose since if the
  51. * Flipper is in EXT clk mode, once a transfer() is started, there
  52. * would be no way to both prevent transfer() from being called again
  53. * as well as cancelling/changing what we're wanting to send. Using
  54. * out byte semaphore means a transfer() can be called at any time,
  55. * waited on synchronously for a timeout, and then re-called at a
  56. * later time; while blocking that update if a byte is actually
  57. * in the middle of being transmitted.
  58. */
  59. FuriSemaphore *out_byte_sem;
  60. /* Used to lock out changing things after a certain point. Pinout,
  61. * mode, etc.
  62. * XXX: Might make more sense to use the mutex to protect a flag?
  63. * Maybe a semaphore? Though I think that is the wrong use.
  64. */
  65. FuriMutex *start_mutex;
  66. /*
  67. * The following should probably have the world stopped around them
  68. * if not modified in an interrupt context.
  69. */
  70. uint8_t in;
  71. uint8_t out;
  72. uint8_t shift;
  73. uint8_t nobyte;
  74. /* Should only be changed when not in middle of tx, will affect a lot */
  75. gblink_clk_source source;
  76. /* Can be changed at any time, will only take effect on the next
  77. * transfer.
  78. */
  79. gblink_speed speed;
  80. /*
  81. * The following is based on observing Pokemon trade data
  82. *
  83. * Clocks idle between bytes is nominally 430 us long for burst data,
  84. * 15 ms for idle polling (e.g. waiting for menu selection), some oddball
  85. * 2 ms gaps that appears between one 0xFE byte from the Game Boy every trade;
  86. * clock period is nominally 122 us.
  87. *
  88. * Therefore, if we haven't seen a clock in 500 us, reset our bit counter.
  89. * Note that, this should never actually be a concern, but it is an additional
  90. * safeguard against desyncing.
  91. */
  92. uint32_t time;
  93. uint32_t bitclk_timeout_us;
  94. void *exti_workaround_handle;
  95. };
  96. static inline bool gblink_transfer_in_progress(struct gblink *gblink)
  97. {
  98. return !(furi_semaphore_get_count(gblink->out_byte_sem));
  99. }
  100. /* XXX: TODO: Investigate how exceeding the timeout would work if in INT clock
  101. * mode. I think this would reset the state machine, but, I don't think the
  102. * transfer would be restarted with the correct data.
  103. */
  104. static void gblink_shift_in_isr(struct gblink *gblink)
  105. {
  106. const uint32_t time_ticks = furi_hal_cortex_instructions_per_microsecond() * gblink->bitclk_timeout_us;
  107. if (gblink->source == GBLINK_CLK_INT)
  108. furi_hal_gpio_write(gblink->clk, 1);
  109. /* If we exceeded the bit clock timeout, reset all counters */
  110. if ((DWT->CYCCNT - gblink->time) > time_ticks) {
  111. gblink->in = 0;
  112. gblink->shift = 0;
  113. }
  114. gblink->time = DWT->CYCCNT;
  115. gblink->in <<= 1;
  116. gblink->in |= furi_hal_gpio_read(gblink->serin);
  117. gblink->shift++;
  118. /* If 8 bits transfered, reset shift counter, call registered
  119. * callback, re-set nobyte in output buffer.
  120. */
  121. if (gblink->shift == 8) {
  122. if (gblink->source == GBLINK_CLK_INT)
  123. clock_timer_stop();
  124. gblink->shift = 0;
  125. /*
  126. * Set up next out byte before calling the callback.
  127. * This is in case the callback itself sets a new out
  128. * byte which it will in most cases.
  129. *
  130. * The nobyte value is set in place as the next output byte,
  131. * in case the flipper does not set a real byte before the next
  132. * transfer starts.
  133. */
  134. gblink->out = gblink->nobyte;
  135. furi_semaphore_release(gblink->out_byte_sem);
  136. /*
  137. * Call the callback, if set, and then release the semaphore
  138. * in case a thread is waiting on TX to complete.
  139. */
  140. if (gblink->callback)
  141. gblink->callback(gblink->cb_context, gblink->in);
  142. furi_semaphore_release(gblink->transfer_sem);
  143. }
  144. }
  145. static void gblink_shift_out_isr(struct gblink *gblink)
  146. {
  147. furi_semaphore_acquire(gblink->out_byte_sem, 0);
  148. furi_hal_gpio_write(gblink->serout, !!(gblink->out & 0x80));
  149. gblink->out <<= 1;
  150. /* XXX: TODO: Check that this is the correct thing with open drain.
  151. * does 0 value actually drive the line low, or high?
  152. */
  153. if (gblink->source == GBLINK_CLK_INT)
  154. furi_hal_gpio_write(gblink->clk, 0);
  155. }
  156. static void gblink_clk_isr(void *context)
  157. {
  158. furi_assert(context);
  159. struct gblink *gblink = context;
  160. bool out = false;
  161. /*
  162. * Whether we're shifting in or out is dependent on the clock source.
  163. * If external, and the clock line is high, that means a posedge just
  164. * occurred and we need to shift data in.
  165. *
  166. * If internal, and the clock line is high, that means we're about
  167. * to drive a negedge and need to shift data out.
  168. *
  169. * The actual in/out functions drive the clock state at the right times
  170. * if the clock is internal source.
  171. */
  172. out = (furi_hal_gpio_read(gblink->clk) ==
  173. (gblink->source == GBLINK_CLK_INT));
  174. if (out)
  175. gblink_shift_out_isr(gblink);
  176. else
  177. gblink_shift_in_isr(gblink);
  178. }
  179. /*
  180. * Call to set up the clk pin modes to do the right thing based on if INT or
  181. * EXT clock source is configured.
  182. */
  183. static void gblink_clk_configure(struct gblink *gblink)
  184. {
  185. if (gblink->source == GBLINK_CLK_EXT) {
  186. furi_hal_gpio_init(gblink->clk, GpioModeInterruptRiseFall, GpioPullUp, GpioSpeedVeryHigh);
  187. /* furi_hal_gpio_init, while it sets interrupt settings on the GPIO,
  188. * does not actually enable the EXTI interrupt.
  189. */
  190. gblink_int_enable(gblink);
  191. } else {
  192. /* This will disable the EXTI interrupt for us */
  193. furi_hal_gpio_init(gblink->clk, GpioModeOutputOpenDrain, GpioPullUp, GpioSpeedVeryHigh);
  194. }
  195. }
  196. void gblink_clk_source_set(void *handle, gblink_clk_source source)
  197. {
  198. furi_assert(handle);
  199. struct gblink *gblink = handle;
  200. if (source == gblink->source)
  201. return;
  202. /*
  203. * NOTE:
  204. * I'm not sure the best way to handle this at the moment. In theory,
  205. * it should be safe to check that we're just not in the middle of a
  206. * transfer and not worry about getting stuck.
  207. * However, I'm not really sure how true that is, so for now this will
  208. * always change the source and reset the current byte transfer.
  209. * It is up to the callee to ensure that they are between bytes.
  210. *
  211. * One idea would be to get the semaphore, but wait the set timeout.
  212. * if that is exceeded or the semaphore is acquired, then its probably
  213. * safe to change the source and reset shift register.
  214. */
  215. gblink->source = source;
  216. gblink->shift = 0;
  217. gblink_clk_configure(gblink);
  218. }
  219. void gblink_speed_set(void *handle, gblink_speed speed)
  220. {
  221. furi_assert(handle);
  222. struct gblink *gblink = handle;
  223. /*
  224. * This does not need any protection, it will take effect at the start
  225. * of the next byte.
  226. */
  227. gblink->speed = speed;
  228. }
  229. /* default is set to 500 us */
  230. void gblink_timeout_set(void *handle, uint32_t us)
  231. {
  232. furi_assert(handle);
  233. struct gblink *gblink = handle;
  234. gblink->bitclk_timeout_us = us;
  235. }
  236. int gblink_pin_set(void *handle, gblink_bus_pins pin, const GpioPin *gpio)
  237. {
  238. furi_assert(handle);
  239. struct gblink *gblink = handle;
  240. if (furi_mutex_acquire(gblink->start_mutex, 0) != FuriStatusOk)
  241. return 1;
  242. switch (pin) {
  243. case PIN_SERIN:
  244. gblink->serin = gpio;
  245. break;
  246. case PIN_SEROUT:
  247. gblink->serout = gpio;
  248. break;
  249. case PIN_CLK:
  250. gblink->clk = gpio;
  251. break;
  252. case PIN_SD:
  253. gblink->sd = gpio;
  254. break;
  255. default:
  256. furi_crash();
  257. break;
  258. }
  259. furi_mutex_release(gblink->start_mutex);
  260. return 0;
  261. }
  262. int gblink_pin_set_default(void *handle, gblink_pinouts pinout)
  263. {
  264. furi_assert(handle);
  265. struct gblink *gblink = handle;
  266. if (furi_mutex_acquire(gblink->start_mutex, 0) != FuriStatusOk)
  267. return 1;
  268. gblink->serin = common_pinouts[pinout].serin;
  269. gblink->serout = common_pinouts[pinout].serout;
  270. gblink->clk = common_pinouts[pinout].clk;
  271. gblink->sd = common_pinouts[pinout].sd;
  272. furi_mutex_release(gblink->start_mutex);
  273. return 0;
  274. }
  275. int gblink_pin_get_default(void *handle)
  276. {
  277. furi_assert(handle);
  278. struct gblink *gblink = handle;
  279. int i;
  280. for (i = 0; i < PINOUT_COUNT; i++) {
  281. if (gblink->serin != common_pinouts[i].serin)
  282. continue;
  283. if (gblink->serout != common_pinouts[i].serout)
  284. continue;
  285. if (gblink->clk != common_pinouts[i].clk)
  286. continue;
  287. /* XXX: Currently not checked or used! */
  288. //if (gblink->sd != common_pinouts[pinout].sd;
  289. break;
  290. }
  291. if (i == PINOUT_COUNT)
  292. i = -1;
  293. return i;
  294. }
  295. const GpioPin *gblink_pin_get(void *handle, gblink_bus_pins pin)
  296. {
  297. furi_assert(handle);
  298. struct gblink *gblink = handle;
  299. switch (pin) {
  300. case PIN_SERIN:
  301. return gblink->serin;
  302. case PIN_SEROUT:
  303. return gblink->serout;
  304. case PIN_CLK:
  305. return gblink->clk;
  306. case PIN_SD:
  307. return gblink->sd;
  308. default:
  309. furi_crash();
  310. break;
  311. }
  312. return NULL;
  313. }
  314. int gblink_callback_set(void *handle, void (*callback)(void* cb_context, uint8_t in), void *cb_context)
  315. {
  316. furi_assert(handle);
  317. struct gblink *gblink = handle;
  318. if (furi_mutex_acquire(gblink->start_mutex, 0) != FuriStatusOk)
  319. return 1;
  320. gblink->callback = callback;
  321. gblink->cb_context = cb_context;
  322. furi_mutex_release(gblink->start_mutex);
  323. return 0;
  324. }
  325. int gblink_mode_set(void *handle, gblink_mode mode)
  326. {
  327. furi_assert(handle);
  328. struct gblink *gblink = handle;
  329. if (furi_mutex_acquire(gblink->start_mutex, 0) != FuriStatusOk)
  330. return 1;
  331. gblink->mode = mode;
  332. furi_mutex_release(gblink->start_mutex);
  333. return 0;
  334. }
  335. /* XXX: TODO: This doesn't check for start! */
  336. bool gblink_transfer(void *handle, uint8_t val)
  337. {
  338. furi_assert(handle);
  339. struct gblink *gblink = handle;
  340. bool ret = false;
  341. /* Stop the world, this is to ensure we can safely set the next out byte */
  342. /*
  343. * The reason for and therefore issue of setting the next byte has a few
  344. * points to keep in mind.
  345. *
  346. * First, with EXT clock source, the first hint of the external device
  347. * clocking in data is a negative edge where it would set data. This
  348. * means that the next out byte needs to be set before that.
  349. *
  350. * Second, since the interrupt on the neg clock edge loads the next
  351. * byte in to serout after grabbing the semaphore; we can stop the
  352. * world right now, and set the byte if there is no transfer in
  353. * progress. As soon as the world is resumed, the IRQ will fire, and
  354. * the correct, new, data byte will start to be shifted out.
  355. */
  356. FURI_CRITICAL_ENTER();
  357. /* If we're in the middle of a tranfer, don't let the byte be set. */
  358. if (!gblink_transfer_in_progress(gblink)) {
  359. gblink->out = val;
  360. ret = true;
  361. /*
  362. * Now that we're this far, this means the byte we set will be
  363. * transferred one way or another. Because of that, take the
  364. * transfer semaphore. This gets released once a full byte has
  365. * been transferred. This is for the TX wait function. We cannot
  366. * use the out_byte_sem as if the wait is called immediately
  367. * after the transfer, and no data has yet been shifted out,
  368. * the TX wait function would incorrectly return immediately.
  369. */
  370. furi_semaphore_acquire(gblink->transfer_sem, 0);
  371. }
  372. FURI_CRITICAL_EXIT();
  373. /*
  374. * If the out byte was successfully set, and we're driving the clock,
  375. * turn on our timer for byte transfer.
  376. */
  377. if (ret && gblink->source == GBLINK_CLK_INT)
  378. clock_timer_start(gblink_clk_isr, gblink, gblink->speed);
  379. return ret;
  380. }
  381. uint8_t gblink_transfer_tx_wait_complete(void *handle)
  382. {
  383. struct gblink *gblink = handle;
  384. /* XXX: TODO: Think about how to implement this in a way that we can
  385. * use the semaphore to see if there is a transfer waiting to happen,
  386. * but not in a way that would incorrectly show a transfer waiting. e.g.
  387. * if this takes the semaphore, then the semaphore is in the same state
  388. * as if a transfer was in progress. Should this put back the semaphore
  389. * after acquiring it? Is there a better way of handling it?
  390. */
  391. furi_semaphore_acquire(gblink->transfer_sem, FuriWaitForever);
  392. return gblink->in;
  393. }
  394. void gblink_nobyte_set(void *handle, uint8_t val)
  395. {
  396. struct gblink *gblink = handle;
  397. /*
  398. * This is safe to run at any time. It is only copied in after a byte
  399. * transfer is completed.
  400. */
  401. gblink->nobyte = val;
  402. }
  403. void gblink_int_enable(void *handle)
  404. {
  405. furi_assert(handle);
  406. struct gblink *gblink = handle;
  407. /*
  408. * NOTE: This is currently safe to run even with the exti workaround
  409. * in effect. It just enables the root EXTI interrupt source of the
  410. * given pin.
  411. */
  412. furi_hal_gpio_enable_int_callback(gblink->clk);
  413. }
  414. void gblink_int_disable(void *handle)
  415. {
  416. furi_assert(handle);
  417. struct gblink *gblink = handle;
  418. /*
  419. * NOTE: This is currently safe to run even with the exti workaround
  420. * in effect. It just disables the root EXTI interrupt source of the
  421. * given pin.
  422. */
  423. furi_hal_gpio_disable_int_callback(gblink->clk);
  424. }
  425. void *gblink_alloc(void)
  426. {
  427. struct gblink *gblink;
  428. /* Allocate and zero struct */
  429. gblink = malloc(sizeof(struct gblink));
  430. //gblink->spec = malloc(sizeof(struct gblink_spec));
  431. gblink->transfer_sem = furi_semaphore_alloc(1, 1);
  432. gblink->out_byte_sem = furi_semaphore_alloc(1, 1);
  433. gblink->start_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
  434. /* Set defaults */
  435. gblink_pin_set_default(gblink, PINOUT_ORIGINAL);
  436. gblink_mode_set(gblink, GBLINK_MODE_GBC);
  437. gblink_clk_source_set(gblink, GBLINK_CLK_EXT);
  438. gblink_speed_set(gblink, GBLINK_SPD_8192HZ);
  439. gblink_timeout_set(gblink, 500);
  440. /* Set current time to start timeout calculations */
  441. gblink->time = DWT->CYCCNT;
  442. return gblink;
  443. }
  444. void gblink_start(void *handle)
  445. {
  446. furi_assert(handle);
  447. struct gblink *gblink = handle;
  448. /* XXX: Check callback is valid */
  449. furi_mutex_acquire(gblink->start_mutex, FuriWaitForever);
  450. /* Set up pins */
  451. /* TODO: Set up a list of pins that are not safe to use with interrupts.
  452. * I do believe the main FURI GPIO struct has this data baked in so that
  453. * could be used. For now though, we're only checking for the MALVEKE
  454. * pinout which uses a clk pin that has its IRQ shared with the Okay
  455. * button.
  456. * See the work done in pokemon trade tool custom pinout selection for
  457. * an idea of how to check all that.
  458. */
  459. furi_hal_gpio_write(gblink->serout, false);
  460. furi_hal_gpio_init(gblink->serout, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
  461. furi_hal_gpio_write(gblink->serin, false);
  462. furi_hal_gpio_init(gblink->serin, GpioModeInput, GpioPullUp, GpioSpeedVeryHigh);
  463. /* Set up interrupt on clock pin */
  464. if (gblink->clk == &gpio_ext_pb3) {
  465. /* The clock pin is on a pin that is not safe to set an interrupt
  466. * on, so we do a gross workaround to get an interrupt enabled
  467. * on that pin in a way that can be undone safely later with
  468. * no impact to the shared IRQ.
  469. */
  470. gblink->exti_workaround_handle = exti_workaround(gblink->clk, gblink_clk_isr, gblink);
  471. } else {
  472. /* This may not be needed after NFC refactor */
  473. furi_hal_gpio_remove_int_callback(gblink->clk);
  474. furi_hal_gpio_add_int_callback(gblink->clk, gblink_clk_isr, gblink);
  475. }
  476. /* The above immediately enables the interrupt, we don't want
  477. * that just yet and we want configure to handle it.
  478. */
  479. gblink_int_disable(gblink);
  480. gblink_clk_configure(gblink);
  481. }
  482. void gblink_stop(void *handle)
  483. {
  484. furi_assert(handle);
  485. struct gblink *gblink = handle;
  486. /* If we can acquire the mutex, that means start was never actually
  487. * called. Crash.
  488. * XXX: Probably a bit harsh to just crash, can it gracefully recover
  489. * without too much effort?
  490. */
  491. if (furi_mutex_acquire(gblink->start_mutex, 0) == FuriStatusOk) {
  492. furi_crash();
  493. return;
  494. }
  495. if (gblink->clk == &gpio_ext_pb3) {
  496. /* This handles switching the IVT back and putting the EXTI
  497. * regs and pin regs in a valid state for normal use.
  498. */
  499. exti_workaround_undo(gblink->exti_workaround_handle);
  500. } else {
  501. /* Remove interrupt, set IO to sane state */
  502. furi_hal_gpio_remove_int_callback(gblink->clk);
  503. }
  504. furi_hal_gpio_init_simple(gblink->serin, GpioModeAnalog);
  505. furi_hal_gpio_init_simple(gblink->serout, GpioModeAnalog);
  506. furi_hal_gpio_init_simple(gblink->clk, GpioModeAnalog);
  507. furi_mutex_release(gblink->start_mutex);
  508. }
  509. void gblink_free(void *handle)
  510. {
  511. furi_assert(handle);
  512. struct gblink *gblink = handle;
  513. /* If we cannot acquire the mutex, that means the link was never properly
  514. * stopped. Crash.
  515. * XXX: Can this be gracefully handled?
  516. */
  517. if (furi_mutex_acquire(gblink->start_mutex, 0) != FuriStatusOk) {
  518. furi_crash();
  519. return;
  520. }
  521. furi_mutex_release(gblink->start_mutex);
  522. furi_mutex_free(gblink->start_mutex);
  523. furi_semaphore_free(gblink->transfer_sem);
  524. furi_semaphore_free(gblink->out_byte_sem);
  525. free(gblink);
  526. }