override.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /*
  2. * CNC-remote-control
  3. * Feed override switch
  4. *
  5. * Copyright (C) 2011-2016 Michael Buesch <m@bues.ch>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * version 2 as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include "override.h"
  17. #include "util.h"
  18. #include "lcd.h"
  19. #include "main.h"
  20. #include <avr/io.h>
  21. #include <avr/eeprom.h>
  22. #include <avr/interrupt.h>
  23. #include <avr/wdt.h>
  24. #define ADC_HYST 4
  25. #define ADC_MINMAX_DEADBAND 4
  26. #define ADC_REAL_MIN 0
  27. #define ADC_REAL_MAX 0x3FF
  28. #define ADC_MIN (ADC_REAL_MIN + ADC_MINMAX_DEADBAND)
  29. #define ADC_MAX (ADC_REAL_MAX - ADC_MINMAX_DEADBAND)
  30. static uint16_t last_override_adc;
  31. static uint8_t last_override_pos;
  32. static void adc_trigger(bool freerunning)
  33. {
  34. /* Start ADC0 with AVCC reference and a prescaler of 128. */
  35. ADMUX = (1 << REFS0);
  36. ADCSRA = (1 << ADEN) | (0 << ADIE) | (1 << ADSC) |
  37. (freerunning ? (1 << ADATE) : 0) |
  38. (1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2);
  39. }
  40. static inline void adc_busywait(void)
  41. {
  42. do { } while (ADCSRA & (1 << ADSC));
  43. ADCSRA |= (1 << ADIF); /* Clear IRQ flag */
  44. }
  45. void override_init(void)
  46. {
  47. last_override_adc = ADC_REAL_MIN;
  48. last_override_pos = 0;
  49. /* Discard the first measurement */
  50. adc_trigger(0);
  51. adc_busywait();
  52. /* Start the ADC in freerunning mode. */
  53. adc_trigger(1);
  54. }
  55. uint8_t override_get_pos(void)
  56. {
  57. uint16_t adc;
  58. uint8_t pos;
  59. if (!(ADCSRA & (1 << ADIF))) {
  60. /* There was no new conversion */
  61. return last_override_pos;
  62. }
  63. adc = ADC;
  64. ADCSRA |= (1 << ADIF); /* Clear IRQ flag */
  65. if (adc <= ADC_MIN)
  66. adc = ADC_REAL_MIN;
  67. else if (adc >= ADC_MAX)
  68. adc = ADC_REAL_MAX;
  69. else if (abs((int16_t)adc - (int16_t)last_override_adc) <= ADC_HYST)
  70. adc = last_override_adc;
  71. if (adc == last_override_adc)
  72. return last_override_pos;
  73. pos = (uint8_t)(((uint32_t)adc - (uint32_t)ADC_REAL_MIN) * (uint32_t)0xFF /
  74. ((uint32_t)ADC_REAL_MAX - (uint32_t)ADC_REAL_MIN));
  75. last_override_adc = adc;
  76. last_override_pos = pos;
  77. return pos;
  78. }