timer.c 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. * =====================================================================================
  3. *
  4. * ________ .__ __ ________ ____ ________
  5. * \_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
  6. * / / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
  7. * / \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
  8. * \_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
  9. * \__> \/ \/ \/ \/ \/
  10. *
  11. * www.optixx.org
  12. *
  13. *
  14. * Version: 1.0
  15. * Created: 07/21/2009 03:32:16 PM
  16. * Author: david@optixx.org
  17. *
  18. * =====================================================================================
  19. */
  20. #include <stdint.h>
  21. #include <stdio.h>
  22. #include <avr/io.h>
  23. #include <avr/io.h>
  24. #include <avr/interrupt.h> /* for sei() */
  25. #include "debug.h"
  26. #include "info.h"
  27. #include "sram.h"
  28. extern uint8_t snes_reset_line;
  29. #ifndef OCR1A
  30. #define OCR1A OCR1 // 2313 support
  31. #endif
  32. #ifndef WGM12
  33. #define WGM12 CTC1 // 2313 support
  34. #endif
  35. // #define XTAL 11059201L // nominal value
  36. #define XTAL 20000000UL
  37. #define DEBOUNCE 500L // debounce clock (256Hz = 4msec)
  38. #define uint8_t unsigned char
  39. #define uint unsigned int
  40. uint16_t prescaler;
  41. uint16_t volatile second; // count seconds
  42. ISR(SIG_OUTPUT_COMPARE1A)
  43. {
  44. #if XTAL % DEBOUNCE // bei rest
  45. OCR1A = 20000000UL / DEBOUNCE - 1; // compare DEBOUNCE - 1 times
  46. #endif
  47. if (--prescaler == 0) {
  48. prescaler = (uint16_t) DEBOUNCE;
  49. second++; // exact one second over
  50. #if XTAL % DEBOUNCE // handle remainder
  51. OCR1A = XTAL / DEBOUNCE + XTAL % DEBOUNCE - 1; // compare once per second
  52. #endif
  53. }
  54. }
  55. void timer_start(void)
  56. {
  57. TCCR1B = (1 << WGM12) | (1 << CS10); // divide by 1
  58. // clear on compare
  59. OCR1A = XTAL / DEBOUNCE - 1UL; // Output Compare Register
  60. TCNT1 = 0; // Timmer startet mit 0
  61. second = 0;
  62. prescaler = (uint16_t) DEBOUNCE; // software teiler
  63. TIMSK1 = 1 << OCIE1A; // beim Vergleichswertes Compare Match
  64. // Interrupt (SIG_OUTPUT_COMPARE1A)
  65. sei();
  66. }
  67. uint16_t timer_stop_int(void)
  68. {
  69. uint16_t t = ((DEBOUNCE - prescaler) / DEBOUNCE) + second;
  70. return t;
  71. }