main.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * 74HC4094 data sniffer
  3. *
  4. * Copyright (C) 2010 Michael Buesch <m@bues.ch>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * version 2 as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include "util.h"
  16. #include <avr/io.h>
  17. #include <avr/interrupt.h>
  18. #include <stdint.h>
  19. #include <string.h>
  20. /* System configuration */
  21. #define CPU_HZ 16000000
  22. /* 74HC4094 pin connections */
  23. #define LINE_PORT PORTC
  24. #define LINE_PIN PINC
  25. #define LINE_DDR DDRC
  26. #define LINE_CP 0
  27. #define LINE_DATA 1
  28. #define LINE_STROBE 2
  29. /* UART config */
  30. #define UART_BAUDRATE 115200
  31. #define UART_U2X 0
  32. static uint8_t shiftreg_size;
  33. static uint8_t shiftreg[256]; /* The shiftregister state */
  34. static uint8_t shiftreg_out[sizeof(shiftreg)]; /* The output buffers state */
  35. static inline uint8_t get_cp(void)
  36. {
  37. return !!(LINE_PIN & (1 << LINE_CP));
  38. }
  39. static inline uint8_t get_data(void)
  40. {
  41. return !!(LINE_PIN & (1 << LINE_DATA));
  42. }
  43. static inline uint8_t get_strobe(void)
  44. {
  45. return !!(LINE_PIN & (1 << LINE_STROBE));
  46. }
  47. static inline void shift_in_bit(uint8_t bit)
  48. {
  49. uint8_t tmp, iterator;
  50. void *regptr;
  51. irq_disable();
  52. iterator = shiftreg_size;
  53. if (!iterator)
  54. goto out;
  55. regptr = shiftreg;
  56. __asm__ __volatile__(
  57. " clc \n"
  58. " sbrc %[data_bit], 0 \n"
  59. " sec \n"
  60. "1: \n"
  61. " ld %[tmp], Z \n"
  62. " rol %[tmp] \n"
  63. " st Z+, %[tmp] \n"
  64. " dec %[i] \n"
  65. " brne 1b \n"
  66. : [tmp] "=d" (tmp)
  67. , [regptr] "=z" (regptr)
  68. , [i] "=d" (iterator)
  69. : [data_bit] "d" (bit)
  70. , "1" (regptr)
  71. , "2" (iterator)
  72. );
  73. out:
  74. irq_enable();
  75. }
  76. static inline void outbuf_update(void)
  77. {
  78. irq_disable();
  79. memcpy(shiftreg_out, shiftreg, shiftreg_size);
  80. irq_enable();
  81. }
  82. static void uart_tx(uint8_t byte)
  83. {
  84. while (!(UCSRA & (1 << UDRE)));
  85. UDR = byte;
  86. }
  87. ISR(USART_RXC_vect)
  88. {
  89. uint8_t new_size = UDR;
  90. uint8_t i;
  91. for (i = 0; i < shiftreg_size; i++)
  92. uart_tx(shiftreg_out[i]);
  93. if (shiftreg_size != new_size) {
  94. shiftreg_size = new_size;
  95. memset(shiftreg, 0, sizeof(shiftreg));
  96. memset(shiftreg_out, 0, sizeof(shiftreg_out));
  97. }
  98. }
  99. static void uart_init(void)
  100. {
  101. /* Set baud rate */
  102. UBRRL = lo8((CPU_HZ / 16 / UART_BAUDRATE) * (UART_U2X ? 2 : 1));
  103. UBRRH = hi8((CPU_HZ / 16 / UART_BAUDRATE) * (UART_U2X ? 2 : 1))
  104. & ~(1 << URSEL);
  105. UCSRA = ((UART_U2X ? 1 : 0) << U2X);
  106. /* 8 Data bits, 1 Stop bit, No parity */
  107. UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);
  108. /* Enable transceiver */
  109. UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
  110. }
  111. int main(void)
  112. {
  113. uint8_t reg_changed = 0;
  114. irq_disable();
  115. LINE_DDR = 0x00;
  116. LINE_PORT = ~((1 << LINE_CP) | (1 << LINE_DATA) | (1 << LINE_STROBE));
  117. uart_init();
  118. irq_enable();
  119. while (1) {
  120. if (get_cp()) {
  121. /* CP high pulse */
  122. shift_in_bit(get_data());
  123. while (get_cp()); /* Wait for falling edge */
  124. reg_changed = 1;
  125. }
  126. if (reg_changed && get_strobe()) {
  127. reg_changed = 0;
  128. outbuf_update();
  129. }
  130. }
  131. }