src/timer.c
changeset 78 504c2310cddb
parent 63 e9b478c817df
equal deleted inserted replaced
77:975a2dffdcda 78:504c2310cddb
    16             // no PWM
    16             // no PWM
    17         |   0b00 << WGM10
    17         |   0b00 << WGM10
    18     );
    18     );
    19     TCCR1B = (
    19     TCCR1B = (
    20             // CTC mode
    20             // CTC mode
    21             0b01 << WGM12 
    21             0b01 << WGM12
    22     );
    22     );
    23     TCCR1C = 0;
    23     TCCR1C = 0;
       
    24 }
       
    25 
       
    26 static void timer1_set ()
       
    27 {
       
    28     sbi(&TIMER_FLAGS, TIMER1_BUSY);
    24 }
    29 }
    25 
    30 
    26 void timer1_start (short cycles)
    31 void timer1_start (short cycles)
    27 {
    32 {
    28     // count up from zero...
    33     // count up from zero...
    30 
    35 
    31     // ...to the given number of timer cycles
    36     // ...to the given number of timer cycles
    32     OCR1A = cycles;
    37     OCR1A = cycles;
    33 
    38 
    34     // start!
    39     // start!
    35     sbi(&TIMER_FLAGS, TIMER1_BUSY);
    40     timer1_set();
    36     TIMSK1 = (
    41     TIMSK1 = (
    37             // OCA interrupt
    42             // OCA interrupt
    38             0b1 << OCIE1A       // enable
    43             0b1 << OCIE1A       // enable
    39     );
    44     );
    40     TCCR1B = (
    45     TCCR1B = (
    44             // clocksource
    49             // clocksource
    45         |   0b101 << CS10       // 1024'th
    50         |   0b101 << CS10       // 1024'th
    46     );
    51     );
    47 }
    52 }
    48 
    53 
       
    54 /*
       
    55  * Keep the timer running, but clear the flag..
       
    56  */
       
    57 static void timer1_clear ()
       
    58 {
       
    59     cbi(&TIMER_FLAGS, TIMER1_BUSY);
       
    60 }
       
    61 
       
    62 /*
       
    63  * Stop the timer at its current value.
       
    64  */
    49 static void timer1_stop ()
    65 static void timer1_stop ()
    50 {
    66 {
    51     // WGM: normal
    67     // WGM: normal
    52     // clocksource: stop
    68     // clocksource: stop
    53     TCCR1B = 0;
    69     TCCR1B = 0;
    54 
    70 
    55     cbi(&TIMER_FLAGS, TIMER1_BUSY);
    71     timer1_clear();
    56 }
    72 }
    57 
    73 
    58 ISR(TIMER1_COMPA_vect)
    74 ISR(TIMER1_COMPA_vect)
    59 {
    75 {
    60     timer1_stop();
    76     timer1_clear();
    61 
    77 
    62     // XXX: cpu will automatically wake up from sleep()
    78     // cpu will wake up from sleep()
    63 }
    79 }
    64 
    80 
    65 /*
    81 /*
    66  * Sleep on timer1 interrupt.
    82  * Sleep on timer1 interrupt.
    67  *
    83  *
    68  * Returns 0 on interrupt, 1 on timeout.
    84  * Starts fresh timer that sleeps given cycles if given, or continues on the running timer.
       
    85  *
       
    86  * Returns 1 on timeout, 0 on other interrupt.
    69  */
    87  */
    70 char timer_sleep (unsigned cycles)
    88 char timer_sleep (unsigned cycles)
    71 {
    89 {
    72     if (cycles) {
    90     if (cycles) {
    73         // set timer
    91         // set fresh timer
    74         timer1_start(cycles);
    92         timer1_start(cycles);
       
    93     } else {
       
    94         // wait for next cycle...
       
    95         timer1_set();
    75     }
    96     }
    76 
    97 
    77     // sleep
    98     // sleep while timer is running
    78     // TODO: PRR
    99     // XXX: atomic?
    79     SMCR = (
   100     if (tbi(&TIMER_FLAGS, TIMER1_BUSY)) {
    80             // idle sleep
   101         // TODO: PRR
    81             (0b00 << SM0)
   102         SMCR = (
       
   103                 // idle sleep
       
   104                 (0b00 << SM0)
    82 
   105 
    83             // enable sleep
   106                 // enable sleep
    84         |   (0b1 << SE)
   107             |   (0b1 << SE)
    85     );
   108         );
    86     
       
    87     // sleep
       
    88     __asm__ ( "sleep" :: );
       
    89 
   109 
    90     // cleanup
   110         // sleep
    91     SMCR = 0;
   111         __asm__ ( "sleep" :: );
    92     
   112 
    93     if (cycles && !tbi(&TIMER_FLAGS, TIMER1_BUSY)) {
   113         // cleanup
       
   114         SMCR = 0;
       
   115     }
       
   116 
       
   117     if (tbi(&TIMER_FLAGS, TIMER1_BUSY)) {
       
   118         // interrupt
       
   119         return 0;
       
   120 
       
   121     } else {
    94         // timeout
   122         // timeout
    95         return 1;
   123         return 1;
    96     } else {
       
    97         timer1_stop();
       
    98 
       
    99         // interrupt
       
   100         return 0;
       
   101     }
   124     }
   102 }
   125 }
   103 
   126 
   104 
   127