fmrx.c 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /*
  2. * Receive an FM-modulated signal by using a timer with input capture
  3. */
  4. #include "usbcas.h"
  5. static uint16_t one_bit_lo, one_bit_hi; /* Range for an edge being a "1" */
  6. void fmrx_init(void)
  7. {
  8. /* Stop counter */
  9. TCCR1B = 0;
  10. /* Normal mode, no comparators */
  11. TCCR1A = 0;
  12. /* Enable interrupts on input capture */
  13. TIMSK1 = (1 << ICIE1);
  14. /* Clear timer counter */
  15. TCNT1 = 0;
  16. /* Input capture noise canceler on, no prescaler, normal mode;
  17. * start timer
  18. */
  19. TCCR1B = (1 << ICNC1) + (1 << CS10);
  20. }
  21. static uint16_t bytes;
  22. void fmrx_set_speed(uint32_t baudrate)
  23. {
  24. one_bit_lo = F_CPU / (4 * baudrate);
  25. one_bit_hi = 3 * one_bit_lo;
  26. bytes = 0;
  27. }
  28. /* We "hunt" for a block until we find this bit pattern; same as ABC800 */
  29. #define CAS_SYNC_PATTERN 0x0216
  30. #define CAS_BLOCK_LEN (1+1+2+253+1+2) /* STX+type+num+data+ETX+checksum */
  31. /* Interrupt routine for edge capture */
  32. ISR(TIMER1_CAPT_vect)
  33. {
  34. static uint16_t last_edge;
  35. static uint16_t data;
  36. static uint8_t bits;
  37. uint16_t edge, delta;
  38. TCCR1B ^= (1 << ICES1); /* Next edge -> opposite polarity */
  39. edge = ICR1;
  40. delta = edge - last_edge;
  41. last_edge = edge;
  42. if (delta < one_bit_lo) {
  43. /* Early edge, no action */
  44. return;
  45. } else if (delta < one_bit_hi) {
  46. /* A data bit edge */
  47. data |= 1;
  48. } else {
  49. /* Clock edge */
  50. if (bytes) {
  51. if (--bits == 0) {
  52. fmrx_recv_byte(data);
  53. data = 0; /* To avoid false sync */
  54. bits = 8;
  55. bytes--;
  56. }
  57. } else if (data == CAS_SYNC_PATTERN) {
  58. bits = 8;
  59. bytes = CAS_BLOCK_LEN;
  60. }
  61. data <<= 1;
  62. }
  63. }