main.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #include <avr/io.h>
  2. #include <util/delay.h>
  3. static inline void errBlinky(uint16_t repeat);
  4. /* Qualcomm AR9271 802.11n chip needs firmware from the manufacturer, but they
  5. * are not capable of producing reliable software. During normal use they
  6. * require their chip to be reset for continued operation.
  7. *
  8. * There is no documentation on when one might need to perform this reset.
  9. * Based on some observation I found that the both chip and firmware support
  10. * controlling a LED from the USB host. When the manufacturer's firmware is
  11. * requiring the host to perform the reset controlling the LEDs does not work
  12. * as expected, indicating the request for reset.
  13. *
  14. * Yes, I understand how dumb this is, but one must understand the situation
  15. * that Qualcomm is in. If they knew what they were doing things would be
  16. * different, and that, might cause them some concern.
  17. *
  18. * --
  19. *
  20. * Monitor the LED output, the host should blink the LED once per second. We
  21. * will blink our LED in sync with their LED and blink rapidly if we are
  22. * resetting the AR9271.
  23. */
  24. int main(void) {
  25. // Set our led to output
  26. DDRB |= _BV(PB5);
  27. // Set input (pin labeled 12), connect this to the AR9271 LED output
  28. DDRB &= ~_BV(PB4);
  29. uint8_t last = 0;
  30. uint8_t count = 0;
  31. for(;;) {
  32. uint8_t status = 0;
  33. // host must keep the LED on for a minimum of one second per Nyquist-Shannon Sampling Theorem
  34. for(uint8_t i = 10; i--;) {
  35. // mirror our led to the AR9271 led, and remember it's status
  36. if(status = (PINB & _BV(PB4))) PORTB |= _BV(PB5); else PORTB &= ~_BV(PB5);
  37. // do this over about 500ms (one half second, we are in a fixed length loop)
  38. _delay_ms(50);
  39. }
  40. // compare the recorded state to the last state, it should alternate
  41. if(++count && last != status) count = 0;
  42. // stash status to compare next time...
  43. last = status;
  44. // if the counter is small we can skip reset
  45. if(3 >= count) continue; else count = 0;
  46. // power off USB device
  47. { // switch outputs to high impedance rather than "turning off", same effect
  48. DDRB &= ~ (_BV(PB2) | _BV(PB3));
  49. // wait three seconds (50 thousandths of a minute)
  50. errBlinky(50);
  51. }
  52. // power on USB device, computer will load firmware into it
  53. { // Set relay (pins labeled 10 and 11) to output.
  54. DDRB |= (_BV(PB2) | _BV(PB3));
  55. // [!] Use digital pins as power source, relay coil should be >200 Ohms
  56. PORTB |= _BV(PB2);
  57. PORTB &= ~_BV(PB3);
  58. // let the relay pull in, click, clack, and whatever
  59. _delay_ms(100);
  60. // drop power consumption (switch pin 11 to high impedance)
  61. DDRB &= ~_BV(PB3);
  62. // failure after power-up is unlikely, should consider computer boot time
  63. errBlinky(3000 /* thousandths of a minute is three minutes */);
  64. }
  65. }
  66. return 0;
  67. }
  68. static inline void errBlinky(uint16_t repeat) {
  69. // limit repeat to a maximum of about three minutes
  70. repeat = (3000 < repeat) ?3000 :repeat;
  71. // alternate our led every one thousandths of a minute to show error state
  72. for(;repeat--;) { PORTB ^= _BV(PB5); _delay_ms(60); }
  73. }
  74. /* some numbers regarding the relay and our arduino pro mini
  75. * we are using a 3V3 Pro Mini connected to a Omron G6DS-1A-H5
  76. * the relay says it must switch at 70% of rated 5V, which is 3V5 so we
  77. * are under powering the relay, cross your fingers
  78. *
  79. * the relay datasheet claims an operate time of 10ms max, so when we switch
  80. * it 100ms is plenty for debounce. We will also pull back the current using
  81. * a current limit resistor, the datasheet claims 5% of rated voltage for must
  82. * release. We use a 200 Ohm resistor and the coil is 208 Ohm. We might push
  83. * about 8mA current with our 3V3 digital pin, so that'll be interesting if
  84. * that works.
  85. *
  86. * [?] attempting to power the relay with a diode on PB3 and a resistor on
  87. * PB2 was not enough, using a test PSU 3V0 is enough to energize relay, but
  88. * it was right on the edge. I ended up putting a PNP transistor on PB3 with
  89. * it's emitter on the 5V rail, this is more than enough. Code obviously needs
  90. * to be adjusted because we want PB3 and PB2 to oppose each other. The Zener
  91. * is used to make sure that when PB3 floats it isn't pulled to 3V3 by the
  92. * 328p digital input pin proection diodes. 2V1 seemed to be enough, more is
  93. * fine, but when PB3 is driven to ground the base of the PNP does need to come
  94. * down a bit less than the 5V so 4V2 might be the limit on the Zener or the relay
  95. * may not energize. I did test with two series silicon diodes with the opposite
  96. * polarity hoping the 1V2 forward voltage was enough to let the base float to 5V
  97. * but it did not work.
  98. *
  99. *
  100. * Arduino 3V3 Pro Mini
  101. * +---------------+
  102. * | o o o o o o | ___
  103. * |o o| <raw> -------|___> 5V
  104. * |o _ _ o| <gnd> -----+
  105. * |o | | | | o| <rst> |
  106. * |o '-' '-' o| <3v3> |
  107. * |o . o| V
  108. * |o .` `. o|
  109. * |o < > o|
  110. * |o '. .' o|
  111. * |o ' o| <led> (PB5) error indicator
  112. * |o ___ o| <input> (PB4) ----------------+--------+
  113. * |o -/ _ \- o| <output> (PB3) ------+ | |
  114. * |o -\___/- o| <output> (PB2) --+ | .-. .-.
  115. * +---------------+ | .-. |=| |R| pulldown
  116. * | |R| |D| '-'
  117. * .-. '-' '-' |
  118. * |R| | | |
  119. * +-------------+ +---+---+ '-' .-. | V
  120. * | G6DS c | | | | | |Z| 2V1 |___
  121. * | relay o +----+ .-. +----+ |=| Zener |___> AR9271_LED
  122. * | i | |=|f | '-'
  123. * | sw l+----+ |D|l | | ___
  124. * +--+---+------+ | '-'y | | E--|___> 5V
  125. * | | | | b d | +--B
  126. * | |___ | | a i | C--+
  127. * | |___> 5V +---+ c o | |
  128. * |___ | k d +---------+
  129. * |___> AR9271_POWER | e
  130. * V
  131. */