Commit fcce7868a2fe2ef028b7f6c1741a12380b82a9cc
authorbsekisser <squirmyworms@embarqmail.com>
Tue, 4 Mar 2014 21:50:20 +0000 (16:50 -0500)
committerbsekisser <squirmyworms@embarqmail.com>
Sat, 2 Aug 2014 21:07:57 +0000 (17:07 -0400)
avr_timer_reconfigure: calculations moved back in call chain to
 avr_timer_write.

avr_timer_configure: use data processed in avr_timer_write.

avr_timer_init: changed to fully trap writes going to as2,
 clock select bits and waveform generation mode bits.

modified:   ../../simavr/sim/avr_timer.c
modified:   ../../simavr/sim/avr_timer.h

avr_timer: remove as2 timer check.

modified:   avr_timer.c

2 files changed:
simavr/sim/avr_timer.c
simavr/sim/avr_timer.h

index ee2f222206824f24913600e3a17deb3ab4e81f86..5ed574523f346ad67d5a2cf15ba17576b7dfed33 100644 (file)
@@ -247,44 +247,29 @@ static void avr_timer_reconfigure(avr_timer_t * p)
        
        avr_timer_cancel_all_cycle_timers(avr, p);
 
-       long clock = avr->frequency;
-
-       // only can exists on "asynchronous" 8 bits timers
-       if (avr_regbit_get(avr, p->as2))
-               clock = 32768;
-
-       uint8_t cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs));
-       if (cs == 0) {
-               AVR_LOG(avr, LOG_TRACE, "TIMER: %s-%c clock turned off\n", __FUNCTION__, p->name);
-               return;
-       }
-
-       uint8_t mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm));
-       uint8_t cs_div = p->cs_div[cs];
-       uint32_t f = clock >> cs_div;
-
-       p->mode = p->wgm_op[mode];
-       //printf("%s-%c clock %d, div %d(/%d) = %d ; mode %d\n", __FUNCTION__, p->name, clock, cs, 1 << cs_div, f, mode);
-       switch (p->mode.kind) {
+       switch (p->wgm_op_mode_kind) {
                case avr_timer_wgm_normal:
-                       avr_timer_configure(p, f, (1 << p->mode.size) - 1);
+                       avr_timer_configure(p, p->cs_div_clock, p->wgm_op_mode_size);
                        break;
                case avr_timer_wgm_fc_pwm:
-                       avr_timer_configure(p, f, (1 << p->mode.size) - 1);
+                       avr_timer_configure(p, p->cs_div_clock, p->wgm_op_mode_size);
                        break;
                case avr_timer_wgm_ctc: {
-                       avr_timer_configure(p, f, _timer_get_ocr(p, AVR_TIMER_COMPA));
+                       avr_timer_configure(p, p->cs_div_clock, _timer_get_ocr(p, AVR_TIMER_COMPA));
                }       break;
                case avr_timer_wgm_pwm: {
-                       uint16_t top = p->mode.top == avr_timer_wgm_reg_ocra ? _timer_get_ocr(p, AVR_TIMER_COMPA) : _timer_get_icr(p);
-                       avr_timer_configure(p, f, top);
+                       uint16_t top = p->mode.top == (avr_timer_wgm_reg_ocra ?
+                               _timer_get_ocr(p, AVR_TIMER_COMPA) : _timer_get_icr(p));
+                       avr_timer_configure(p, p->cs_div_clock, top);
                }       break;
                case avr_timer_wgm_fast_pwm:
-                       avr_timer_configure(p, f, (1 << p->mode.size) - 1);
+                       avr_timer_configure(p, p->cs_div_clock, p->wgm_op_mode_size);
                        break;
-               default:
+               default: {
+                       uint8_t mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm));
                        AVR_LOG(avr, LOG_WARNING, "TIMER: %s-%c unsupported timer mode wgm=%d (%d)\n",
                                        __FUNCTION__, p->name, mode, p->mode.kind);
+               }
        }       
 }
 
@@ -298,7 +283,7 @@ static void avr_timer_write_ocr(struct avr_t * avr, avr_io_addr_t addr, uint8_t
        oldv = _timer_get_comp_ocr(avr, comp);
        avr_core_watch_write(avr, addr, v);
 
-       switch (timer->mode.kind) {
+       switch (timer->wgm_op_mode_kind) {
                case avr_timer_wgm_normal:
                        avr_timer_reconfigure(timer);
                        break;
@@ -337,12 +322,46 @@ static void avr_timer_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, v
 
        avr_core_watch_write(avr, addr, v);
 
+       uint8_t new_as2 = avr_regbit_get(avr, p->as2);
+       uint8_t new_cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs));
+       uint8_t new_mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm));
+
        // only reconfigure the timer if "relevant" bits have changed
        // this prevent the timer reset when changing the edge detector
        // or other minor bits
-       if (avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs)) != cs ||
-                       avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm)) != mode ||
-                                       avr_regbit_get(avr, p->as2) != as2) {
+       if (new_cs != cs || new_mode != mode || new_as2 != as2) {
+       /* as2 */
+               long clock;
+
+               // only can exists on "asynchronous" 8 bits timers
+               if (new_as2)
+                       clock = 32768;
+               else
+                       clock = avr->frequency;
+
+       /* cs */
+               if (new_cs == 0) {
+                       // cancel everything
+                       p->comp[AVR_TIMER_COMPA].comp_cycles = 0;
+                       p->comp[AVR_TIMER_COMPB].comp_cycles = 0;
+                       p->comp[AVR_TIMER_COMPC].comp_cycles = 0;
+                       p->tov_cycles = 0;
+       
+                       avr_cycle_timer_cancel(avr, avr_timer_tov, p);
+                       avr_cycle_timer_cancel(avr, avr_timer_compa, p);
+                       avr_cycle_timer_cancel(avr, avr_timer_compb, p);
+                       avr_cycle_timer_cancel(avr, avr_timer_compc, p);
+
+                       AVR_LOG(avr, LOG_TRACE, "TIMER: %s-%c clock turned off\n", __FUNCTION__, p->name);
+                       return;
+               }
+               p->cs_div_clock = clock >> p->cs_div[new_cs];
+
+       /* mode */
+               p->mode = p->wgm_op[new_mode];
+               p->wgm_op_mode_kind = p->mode.kind;
+               p->wgm_op_mode_size = (1 << p->mode.size) - 1;
+
                avr_timer_reconfigure(p);
        }
 }
@@ -464,7 +483,23 @@ void avr_timer_init(avr_t * avr, avr_timer_t * p)
 
        if (p->wgm[0].reg) // these are not present on older AVRs
                avr_register_io_write(avr, p->wgm[0].reg, avr_timer_write, p);
+       if(p->wgm[1].reg && (p->wgm[1].reg != p->wgm[0].reg))
+               avr_register_io_write(avr, p->wgm[1].reg, avr_timer_write, p);
+       if(p->wgm[2].reg && (p->wgm[2].reg != p->wgm[0].reg) && (p->wgm[2].reg != p->wgm[1].reg))
+               avr_register_io_write(avr, p->wgm[2].reg, avr_timer_write, p);
+       if(p->wgm[3].reg && (p->wgm[3].reg != p->wgm[0].reg) && (p->wgm[3].reg != p->wgm[1].reg) && (p->wgm[3].reg != p->wgm[2].reg))
+               avr_register_io_write(avr, p->wgm[3].reg, avr_timer_write, p);
+
        avr_register_io_write(avr, p->cs[0].reg, avr_timer_write, p);
+       if(p->cs[1].reg && (p->cs[1].reg != p->cs[0].reg))
+               avr_register_io_write(avr, p->cs[1].reg, avr_timer_write, p);
+       if(p->cs[2].reg && (p->cs[2].reg != p->cs[0].reg) && (p->cs[2].reg != p->cs[1].reg))
+               avr_register_io_write(avr, p->cs[2].reg, avr_timer_write, p);
+       if(p->cs[3].reg && (p->cs[3].reg != p->cs[0].reg) && (p->cs[3].reg != p->cs[1].reg) && (p->cs[3].reg != p->cs[2].reg))
+               avr_register_io_write(avr, p->cs[3].reg, avr_timer_write, p);
+
+       if(p->as2.reg) // as2 signifies timer/counter 2... therefore must check for register.
+               avr_register_io_write(avr, p->as2.reg, avr_timer_write, p);
 
        // this assumes all the "pending" interrupt bits are in the same
        // register. Might not be true on all devices ?
index 87ec0b4889892ae61ed87252ae7c3759985759c2..71decb70d512e2bb0f9bed56275e3a96ccca0b4d 100644 (file)
@@ -109,10 +109,15 @@ typedef struct avr_timer_t {
 
        avr_regbit_t    wgm[4];
        avr_timer_wgm_t wgm_op[16];
+       avr_timer_wgm_t mode;
+       int             wgm_op_mode_kind;
+       uint32_t        wgm_op_mode_size;
 
-       avr_regbit_t    cs[4];
-       uint8_t                 cs_div[16];
        avr_regbit_t    as2;            // asynchronous clock 32khz
+       avr_regbit_t    cs[4];
+       uint8_t         cs_div[16];
+       uint32_t        cs_div_clock;
+
        avr_regbit_t    icp;            // input capture pin, to link IRQs
        avr_regbit_t    ices;           // input capture edge select
 
@@ -121,7 +126,6 @@ typedef struct avr_timer_t {
        avr_int_vector_t overflow;      // overflow
        avr_int_vector_t icr;   // input capture
 
-       avr_timer_wgm_t mode;
        uint64_t                tov_cycles;
        uint64_t                tov_base;       // when we last were called
        uint16_t                tov_top;        // current top value to calculate tnct