Commit 358619f222d2a3610168eb34a0db2c4b09e4e618
authorMichel Pollet <buserror@gmail.com>
Tue, 22 Dec 2009 16:24:35 +0000 (16:24 +0000)
committerMichel Pollet <buserror@gmail.com>
Tue, 22 Dec 2009 16:24:35 +0000 (16:24 +0000)
Also made a PWM and a Fast PWM mode. Fast pwm doesm't use the
interrupts, as most of the time it's never used. Aldo it kills
performanves when calling a timer every 400 cycles.

Signed-off-by: Michel Pollet <buserror@gmail.com>
7 files changed:
simavr/cores/sim_megax4.h
simavr/cores/sim_megax8.h
simavr/cores/sim_tiny13.c
simavr/cores/sim_tiny2313.c
simavr/cores/sim_tinyx5.h
simavr/sim/avr_timer.c
simavr/sim/avr_timer.h

index f8510973fdac9d2597e6a044b200243199da1dd7..1b252577a318875e3d79f2f0e67e453f170b2510 100644 (file)
@@ -197,8 +197,8 @@ struct mcu_t SIM_CORENAME = {
                .wgm_op = {
                        [0] = AVR_TIMER_WGM_NORMAL8(),
                        [2] = AVR_TIMER_WGM_CTC(),
-                       [3] = AVR_TIMER_WGM_FASTPWM(),
-                       [7] = AVR_TIMER_WGM_FASTPWM(),
+                       [3] = AVR_TIMER_WGM_FASTPWM8(),
+                       [7] = AVR_TIMER_WGM_OCPWM(),
                },
                .cs = { AVR_IO_REGBIT(TCCR0B, CS00), AVR_IO_REGBIT(TCCR0B, CS01), AVR_IO_REGBIT(TCCR0B, CS02) },
                .cs_div = { 0, 0, 3 /* 8 */, 6 /* 64 */, 8 /* 256 */, 10 /* 1024 */ },
@@ -231,9 +231,12 @@ struct mcu_t SIM_CORENAME = {
                .wgm_op = {
                        [0] = AVR_TIMER_WGM_NORMAL16(),
                        [4] = AVR_TIMER_WGM_CTC(),
-                       [5] = AVR_TIMER_WGM_FASTPWM(),
-                       [6] = AVR_TIMER_WGM_FASTPWM(),
-                       [7] = AVR_TIMER_WGM_FASTPWM(),
+                       [5] = AVR_TIMER_WGM_FASTPWM8(),
+                       [6] = AVR_TIMER_WGM_FASTPWM9(),
+                       [7] = AVR_TIMER_WGM_FASTPWM10(),
+                       [12] = AVR_TIMER_WGM_ICCTC(),
+                       [14] = AVR_TIMER_WGM_ICPWM(),
+                       [15] = AVR_TIMER_WGM_OCPWM(),
                },
                .cs = { AVR_IO_REGBIT(TCCR1B, CS10), AVR_IO_REGBIT(TCCR1B, CS11), AVR_IO_REGBIT(TCCR1B, CS12) },
                .cs_div = { 0, 0, 3 /* 8 */, 6 /* 64 */, 8 /* 256 */, 10 /* 1024 */  /* External clock T1 is not handled */},
@@ -241,7 +244,8 @@ struct mcu_t SIM_CORENAME = {
                .r_ocra = OCR1AL,
                .r_ocrb = OCR1BL,
                .r_tcnt = TCNT1L,
-
+               .r_icr = ICR1L,
+               .r_icrh = ICR1H,
                .r_ocrah = OCR1AH,      // 16 bits timers have two bytes of it
                .r_ocrbh = OCR1BH,
                .r_tcnth = TCNT1H,
@@ -273,8 +277,8 @@ struct mcu_t SIM_CORENAME = {
                .wgm_op = {
                        [0] = AVR_TIMER_WGM_NORMAL8(),
                        [2] = AVR_TIMER_WGM_CTC(),
-                       [3] = AVR_TIMER_WGM_FASTPWM(),
-                       [7] = AVR_TIMER_WGM_FASTPWM(),
+                       [3] = AVR_TIMER_WGM_FASTPWM8(),
+                       [7] = AVR_TIMER_WGM_OCPWM(),
                },
                .cs = { AVR_IO_REGBIT(TCCR2B, CS20), AVR_IO_REGBIT(TCCR2B, CS21), AVR_IO_REGBIT(TCCR2B, CS22) },
                .cs_div = { 0, 0, 3 /* 8 */, 5 /* 32 */, 6 /* 64 */, 7 /* 128 */, 8 /* 256 */, 10 /* 1024 */ },
index b18293c7cb9a69c66036c599a14ad5d64797dc63..ed2ac02a3f94a7fc5a8a00b9639818c459b069c8 100644 (file)
@@ -161,8 +161,8 @@ struct mcu_t SIM_CORENAME = {
                .wgm_op = {
                        [0] = AVR_TIMER_WGM_NORMAL8(),
                        [2] = AVR_TIMER_WGM_CTC(),
-                       [3] = AVR_TIMER_WGM_FASTPWM(),
-                       [7] = AVR_TIMER_WGM_FASTPWM(),
+                       [3] = AVR_TIMER_WGM_FASTPWM8(),
+                       [7] = AVR_TIMER_WGM_OCPWM(),
                },
                .cs = { AVR_IO_REGBIT(TCCR0B, CS00), AVR_IO_REGBIT(TCCR0B, CS01), AVR_IO_REGBIT(TCCR0B, CS02) },
                .cs_div = { 0, 0, 3 /* 8 */, 6 /* 64 */, 8 /* 256 */, 10 /* 1024 */ },
@@ -195,9 +195,12 @@ struct mcu_t SIM_CORENAME = {
                .wgm_op = {
                        [0] = AVR_TIMER_WGM_NORMAL16(),
                        [4] = AVR_TIMER_WGM_CTC(),
-                       [5] = AVR_TIMER_WGM_FASTPWM(),
-                       [6] = AVR_TIMER_WGM_FASTPWM(),
-                       [7] = AVR_TIMER_WGM_FASTPWM(),
+                       [5] = AVR_TIMER_WGM_FASTPWM8(),
+                       [6] = AVR_TIMER_WGM_FASTPWM9(),
+                       [7] = AVR_TIMER_WGM_FASTPWM10(),
+                       [12] = AVR_TIMER_WGM_ICCTC(),
+                       [14] = AVR_TIMER_WGM_ICPWM(),
+                       [15] = AVR_TIMER_WGM_OCPWM(),
                },
                .cs = { AVR_IO_REGBIT(TCCR1B, CS10), AVR_IO_REGBIT(TCCR1B, CS11), AVR_IO_REGBIT(TCCR1B, CS12) },
                .cs_div = { 0, 0, 3 /* 8 */, 6 /* 64 */, 8 /* 256 */, 10 /* 1024 */  /* External clock T1 is not handled */},
@@ -205,7 +208,8 @@ struct mcu_t SIM_CORENAME = {
                .r_ocra = OCR1AL,
                .r_ocrb = OCR1BL,
                .r_tcnt = TCNT1L,
-
+               .r_icr = ICR1L,
+               .r_icrh = ICR1H,
                .r_ocrah = OCR1AH,      // 16 bits timers have two bytes of it
                .r_ocrbh = OCR1BH,
                .r_tcnth = TCNT1H,
@@ -238,8 +242,8 @@ struct mcu_t SIM_CORENAME = {
                .wgm_op = {
                        [0] = AVR_TIMER_WGM_NORMAL8(),
                        [2] = AVR_TIMER_WGM_CTC(),
-                       [3] = AVR_TIMER_WGM_FASTPWM(),
-                       [7] = AVR_TIMER_WGM_FASTPWM(),
+                       [3] = AVR_TIMER_WGM_FASTPWM8(),
+                       [7] = AVR_TIMER_WGM_OCPWM(),
                },
 
                .cs = { AVR_IO_REGBIT(TCCR2B, CS20), AVR_IO_REGBIT(TCCR2B, CS21), AVR_IO_REGBIT(TCCR2B, CS22) },
index 3335c10998164c5c8e01393fa07bf3b8d9994fa3..d1a936b1d41f4a9044aa7977b538ef0695a0f8c7 100644 (file)
@@ -75,8 +75,8 @@ static struct mcu_t {
                .wgm_op = {
                        [0] = AVR_TIMER_WGM_NORMAL8(),
                        [2] = AVR_TIMER_WGM_CTC(),
-                       [3] = AVR_TIMER_WGM_FASTPWM(),
-                       [7] = AVR_TIMER_WGM_FASTPWM(),
+                       [3] = AVR_TIMER_WGM_FASTPWM8(),
+                       [7] = AVR_TIMER_WGM_OCPWM(),
                },
                .cs = { AVR_IO_REGBIT(TCCR0B, CS00), AVR_IO_REGBIT(TCCR0B, CS01), AVR_IO_REGBIT(TCCR0B, CS02) },
                .cs_div = { 0, 0, 3 /* 8 */, 6 /* 64 */, 8 /* 256 */, 10 /* 1024 */ },
index cead7f0cc2667147ccf2da129611e80170f429b7..4bb3288c9244ef5dbaf0827af2858e3ba93a6f35 100644 (file)
@@ -105,8 +105,8 @@ static struct mcu_t {
                .wgm_op = {
                        [0] = AVR_TIMER_WGM_NORMAL8(),
                        [2] = AVR_TIMER_WGM_CTC(),
-                       [3] = AVR_TIMER_WGM_FASTPWM(),
-                       [7] = AVR_TIMER_WGM_FASTPWM(),
+                       [3] = AVR_TIMER_WGM_FASTPWM8(),
+                       [7] = AVR_TIMER_WGM_OCPWM(),
                },
                .cs = { AVR_IO_REGBIT(TCCR0B, CS00), AVR_IO_REGBIT(TCCR0B, CS01), AVR_IO_REGBIT(TCCR0B, CS02) },
                .cs_div = { 0, 0, 3 /* 8 */, 6 /* 64 */, 8 /* 256 */, 10 /* 1024 */ },
@@ -139,9 +139,12 @@ static struct mcu_t {
                .wgm_op = {
                        [0] = AVR_TIMER_WGM_NORMAL16(),
                        [4] = AVR_TIMER_WGM_CTC(),
-                       [5] = AVR_TIMER_WGM_FASTPWM(),
-                       [6] = AVR_TIMER_WGM_FASTPWM(),
-                       [7] = AVR_TIMER_WGM_FASTPWM(),
+                       [5] = AVR_TIMER_WGM_FASTPWM8(),
+                       [6] = AVR_TIMER_WGM_FASTPWM9(),
+                       [7] = AVR_TIMER_WGM_FASTPWM10(),
+                       [12] = AVR_TIMER_WGM_ICCTC(),
+                       [14] = AVR_TIMER_WGM_ICPWM(),
+                       [15] = AVR_TIMER_WGM_OCPWM(),
                },
                .cs = { AVR_IO_REGBIT(TCCR1B, CS10), AVR_IO_REGBIT(TCCR1B, CS11), AVR_IO_REGBIT(TCCR1B, CS12) },
                .cs_div = { 0, 0, 3 /* 8 */, 6 /* 64 */, 8 /* 256 */, 10 /* 1024 */  /* External clock T1 is not handled */},
@@ -149,7 +152,8 @@ static struct mcu_t {
                .r_ocra = OCR1AL,
                .r_ocrb = OCR1BL,
                .r_tcnt = TCNT1L,
-
+               .r_icr = ICR1L,
+               .r_icrh = ICR1H,
                .r_ocrah = OCR1AH,      // 16 bits timers have two bytes of it
                .r_ocrbh = OCR1BH,
                .r_tcnth = TCNT1H,
index 8d42268e6903b8a22a30d23eb66c54cd27d392b8..9dda7ed0b58df7abcc46abf7833afb06a7474f78 100644 (file)
@@ -108,8 +108,8 @@ struct mcu_t SIM_CORENAME = {
                .wgm_op = {
                        [0] = AVR_TIMER_WGM_NORMAL8(),
                        [2] = AVR_TIMER_WGM_CTC(),
-                       [3] = AVR_TIMER_WGM_FASTPWM(),
-                       [7] = AVR_TIMER_WGM_FASTPWM(),
+                       [3] = AVR_TIMER_WGM_FASTPWM8(),
+                       [7] = AVR_TIMER_WGM_OCPWM(),
                },
                .cs = { AVR_IO_REGBIT(TCCR0B, CS00), AVR_IO_REGBIT(TCCR0B, CS01), AVR_IO_REGBIT(TCCR0B, CS02) },
                .cs_div = { 0, 0, 3 /* 8 */, 6 /* 64 */, 8 /* 256 */, 10 /* 1024 */ },
index 4f0ac93b030797ba818f22731bbc9aca6c0cf425..10bf174f6d0456ffee43b0c62a583d0a15af8e72 100644 (file)
@@ -47,6 +47,11 @@ static uint16_t _timer_get_tcnt(avr_timer_t * p)
        return p->io.avr->data[p->r_tcnt] |
                                (p->r_tcnth ? (p->io.avr->data[p->r_tcnth] << 8) : 0);
 }
+static uint16_t _timer_get_icr(avr_timer_t * p)
+{
+       return p->io.avr->data[p->r_icr] |
+                               (p->r_tcnth ? (p->io.avr->data[p->r_icrh] << 8) : 0);
+}
 
 static avr_cycle_count_t avr_timer_compa(struct avr_t * avr, avr_cycle_count_t when, void * param)
 {
@@ -156,15 +161,15 @@ static void avr_timer_configure(avr_timer_t * p, uint32_t clock, uint32_t top)
 
        printf("%s-%c clock %d top %d a %d b %d\n", __FUNCTION__, p->name, clock, top, ocra, ocrb);
        p->tov_cycles = frequency / t; // avr_hz_to_cycles(frequency, t);
-       printf("%s-%c TOP %.2fHz = cycles = %d\n", __FUNCTION__, p->name, t, (int)p->tov_cycles);
+       printf("%s-%c TOP %.2fHz = %d cycles\n", __FUNCTION__, p->name, t, (int)p->tov_cycles);
 
        if (ocra && ocra <= top) {
                p->compa_cycles = frequency / fa; // avr_hz_to_cycles(p->io.avr, fa);
-               printf("%s-%c A %.2fHz = cycles = %d\n", __FUNCTION__, p->name, fa, (int)p->compa_cycles);
+               printf("%s-%c A %.2fHz = %d cycles\n", __FUNCTION__, p->name, fa, (int)p->compa_cycles);
        }
        if (ocrb && ocrb <= top) {
                p->compb_cycles = frequency / fb; // avr_hz_to_cycles(p->io.avr, fb);
-               printf("%s-%c B %.2fHz = cycles = %d\n", __FUNCTION__, p->name, fb, (int)p->compb_cycles);
+               printf("%s-%c B %.2fHz = %d cycles\n", __FUNCTION__, p->name, fb, (int)p->compb_cycles);
        }
 
        if (p->tov_cycles > 1) {
@@ -179,6 +184,8 @@ static void avr_timer_reconfigure(avr_timer_t * p)
 {
        avr_t * avr = p->io.avr;
 
+       avr_timer_wgm_t zero={0};
+       p->mode = zero;
        // cancel everything
        p->compa_cycles = 0;
        p->compb_cycles = 0;
@@ -204,23 +211,49 @@ static void avr_timer_reconfigure(avr_timer_t * p)
        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->wgm_op[mode].kind) {
+       switch (p->mode.kind) {
                case avr_timer_wgm_normal:
-                       avr_timer_configure(p, f, (1 << p->wgm_op[mode].size) - 1);
+                       avr_timer_configure(p, f, (1 << p->mode.size) - 1);
                        break;
                case avr_timer_wgm_ctc: {
                        avr_timer_configure(p, f, _timer_get_ocra(p));
                }       break;
-               case avr_timer_wgm_fast_pwm: {
-                       avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocra(p));
-                       avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocra(p));
+               case avr_timer_wgm_pwm: {
+                       uint16_t top = p->mode.top == avr_timer_wgm_reg_ocra ? _timer_get_ocra(p) : _timer_get_icr(p);
+                       avr_timer_configure(p, f, top);
                }       break;
+               case avr_timer_wgm_fast_pwm:
+               //      avr_timer_configure(p, f, (1 << p->mode.size) - 1);
+                       break;
                default:
-                       printf("%s-%c unsupported timer mode wgm=%d (%d)\n", __FUNCTION__, p->name, mode, p->wgm_op[mode].kind);
+                       printf("%s-%c unsupported timer mode wgm=%d (%d)\n", __FUNCTION__, p->name, mode, p->mode.kind);
        }       
 }
 
+static void avr_timer_write_ocr(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
+{
+       avr_timer_t * p = (avr_timer_t *)param;
+       avr_core_watch_write(avr, addr, v);
+       switch (p->mode.kind) {
+               case avr_timer_wgm_pwm:
+                       if (p->mode.top != avr_timer_wgm_reg_ocra) {
+                               avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocra(p));
+                               avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocrb(p));
+                       }
+                       break;
+               case avr_timer_wgm_fast_pwm:
+                       avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocra(p));
+                       avr_raise_irq(p->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocrb(p));
+                       break;
+               default:
+                       printf("%s-%c mode %d\n", __FUNCTION__, p->name, p->mode.kind);
+                       avr_timer_reconfigure(p);
+                       break;
+       }
+}
+
 static void avr_timer_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
 {
        avr_timer_t * p = (avr_timer_t *)param;
@@ -246,7 +279,7 @@ static      avr_io_t        _io = {
 void avr_timer_init(avr_t * avr, avr_timer_t * p)
 {
        p->io = _io;
-       printf("%s timer%c created OCRA %02x OCRAH %02x\n", __FUNCTION__, p->name, p->r_ocra,  p->r_ocrah);
+       //printf("%s timer%c created\n", __FUNCTION__, p->name);
 
        // allocate this module's IRQ
        p->io.irq_count = TIMER_IRQ_COUNT;
@@ -258,6 +291,8 @@ void avr_timer_init(avr_t * avr, avr_timer_t * p)
        avr_register_io(avr, &p->io);
        avr_register_vector(avr, &p->compa);
        avr_register_vector(avr, &p->compb);
+       avr_register_vector(avr, &p->overflow);
+       avr_register_vector(avr, &p->icr);
 
        avr_register_io_write(avr, p->cs[0].reg, avr_timer_write, p);
 
@@ -266,7 +301,7 @@ void avr_timer_init(avr_t * avr, avr_timer_t * p)
         * high bytes because the datasheet says that the low address is always
         * the trigger.
         */
-       avr_register_io_write(avr, p->r_ocra, avr_timer_write, p);
+       avr_register_io_write(avr, p->r_ocra, avr_timer_write_ocr, p);
        avr_register_io_write(avr, p->r_ocrb, avr_timer_write, p);
        avr_register_io_write(avr, p->r_tcnt, avr_timer_tcnt_write, p);
 
index d863532a24569668745850314fb89b90c14ec488..3d0b57561c0003a7e7d6897e54cb63d0bafe019f 100644 (file)
@@ -37,16 +37,27 @@ enum {
        avr_timer_wgm_none = 0, // invalid mode
        avr_timer_wgm_normal,
        avr_timer_wgm_ctc,
+       avr_timer_wgm_pwm,
        avr_timer_wgm_fast_pwm,
 };
+enum {
+       avr_timer_wgm_reg_constant = 0,
+       avr_timer_wgm_reg_ocra,
+       avr_timer_wgm_reg_icr,
+};
 typedef struct avr_timer_wgm_t {
        uint32_t top: 8, bottom: 8, size : 8, kind : 8;
 } avr_timer_wgm_t;
 
 #define AVR_TIMER_WGM_NORMAL8() { .kind = avr_timer_wgm_normal, .size=8 }
 #define AVR_TIMER_WGM_NORMAL16() { .kind = avr_timer_wgm_normal, .size=16 }
-#define AVR_TIMER_WGM_CTC() { .kind = avr_timer_wgm_ctc }
-#define AVR_TIMER_WGM_FASTPWM() { .kind = avr_timer_wgm_fast_pwm }
+#define AVR_TIMER_WGM_CTC() { .kind = avr_timer_wgm_ctc, .top = avr_timer_wgm_reg_ocra }
+#define AVR_TIMER_WGM_ICCTC() { .kind = avr_timer_wgm_ctc, .top = avr_timer_wgm_reg_icr }
+#define AVR_TIMER_WGM_FASTPWM8() { .kind = avr_timer_wgm_fast_pwm, .size=8 }
+#define AVR_TIMER_WGM_FASTPWM9() { .kind = avr_timer_wgm_fast_pwm, .size=9 }
+#define AVR_TIMER_WGM_FASTPWM10() { .kind = avr_timer_wgm_fast_pwm, .size=10 }
+#define AVR_TIMER_WGM_OCPWM() { .kind = avr_timer_wgm_pwm, .top = avr_timer_wgm_reg_ocra }
+#define AVR_TIMER_WGM_ICPWM() { .kind = avr_timer_wgm_pwm, .top = avr_timer_wgm_reg_icr }
 
 typedef struct avr_timer_t {
        avr_io_t        io;
@@ -68,6 +79,7 @@ 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                compa_cycles;
        uint64_t                compb_cycles;
        uint64_t                tov_cycles;