From f66326fab1d65d59a03b5eaa1e86f0bc09077ed4 Mon Sep 17 00:00:00 2001 From: Pascal Pieper Date: Tue, 8 Dec 2020 10:41:13 +0100 Subject: [PATCH 1/2] expand pwm max value to 16 bit for avrs Signed-off-by: Pascal Pieper --- src/avr/gpio.h | 4 ++-- src/avr/hard_pwm.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/avr/gpio.h b/src/avr/gpio.h index 9d98ee709218..c57428d0192d 100644 --- a/src/avr/gpio.h +++ b/src/avr/gpio.h @@ -26,8 +26,8 @@ struct gpio_pwm { void *reg; uint8_t size8; }; -struct gpio_pwm gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint8_t val); -void gpio_pwm_write(struct gpio_pwm g, uint8_t val); +struct gpio_pwm gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint16_t val); +void gpio_pwm_write(struct gpio_pwm g, uint16_t val); struct gpio_adc { uint8_t chan; diff --git a/src/avr/hard_pwm.c b/src/avr/hard_pwm.c index 01d0bd9e6270..9d71330c5446 100644 --- a/src/avr/hard_pwm.c +++ b/src/avr/hard_pwm.c @@ -74,10 +74,10 @@ static const struct gpio_pwm_info pwm_regs[] PROGMEM = { #endif }; -DECL_CONSTANT("PWM_MAX", 255); +DECL_CONSTANT("PWM_MAX", 65535); //16 bit struct gpio_pwm -gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint8_t val) +gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint16_t val) { // Find pin in pwm_regs table const struct gpio_pwm_info *p = pwm_regs; @@ -135,10 +135,10 @@ gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint8_t val) } void -gpio_pwm_write(struct gpio_pwm g, uint8_t val) +gpio_pwm_write(struct gpio_pwm g, uint16_t val) { if (g.size8) { - *(volatile uint8_t*)g.reg = val; + *(volatile uint8_t*)g.reg = val >> 8; // Take the MSB } else { irqstatus_t flag = irq_save(); *(volatile uint16_t*)g.reg = val; From dceb7852ba003351b7685311f6e0c6ec9dbd87d7 Mon Sep 17 00:00:00 2001 From: Pascal Pieper Date: Fri, 11 Dec 2020 12:58:17 +0100 Subject: [PATCH 2/2] TODO: Scaling Signed-off-by: Pascal Pieper --- src/avr/gpio.h | 1 + src/avr/hard_pwm.c | 82 +++++++++++++++++++++++++++++----------------- 2 files changed, 53 insertions(+), 30 deletions(-) diff --git a/src/avr/gpio.h b/src/avr/gpio.h index c57428d0192d..2d4d5f80386a 100644 --- a/src/avr/gpio.h +++ b/src/avr/gpio.h @@ -25,6 +25,7 @@ uint8_t gpio_in_read(struct gpio_in g); struct gpio_pwm { void *reg; uint8_t size8; + uint16_t scale; }; struct gpio_pwm gpio_pwm_setup(uint8_t pin, uint32_t cycle_time, uint16_t val); void gpio_pwm_write(struct gpio_pwm g, uint16_t val); diff --git a/src/avr/hard_pwm.c b/src/avr/hard_pwm.c index 9d71330c5446..ee424fa311cd 100644 --- a/src/avr/hard_pwm.c +++ b/src/avr/hard_pwm.c @@ -16,9 +16,11 @@ struct gpio_pwm_info { uint8_t pin; volatile void *ocr; volatile uint8_t *rega, *regb; + volatile uint16_t *icr; uint8_t en_bit, flags; }; +//AFMT: 4 bit prescaler enum { GP_8BIT=1, GP_AFMT=2 }; static const struct gpio_pwm_info pwm_regs[] PROGMEM = { @@ -55,25 +57,26 @@ static const struct gpio_pwm_info pwm_regs[] PROGMEM = { { GPIO('C', 5), &OCR3B, &TCCR3A, &TCCR3B, 1<flags), cs; - if (flags & GP_AFMT) { - switch (cycle_time) { - case 0 ... (1+8) * 510L / 2 - 1: cs = 1; break; - case (1+8) * 510L / 2 ... (8+32) * 510L / 2 - 1: cs = 2; break; - case (8+32) * 510L / 2 ... (32+64) * 510L / 2 - 1: cs = 3; break; - case (32+64) * 510L / 2 ... (64+128) * 510L / 2 - 1: cs = 4; break; - case (64+128) * 510L / 2 ... (128+256) * 510L / 2 - 1: cs = 5; break; - case (128+256) * 510L / 2 ... (256+1024) * 510L / 2 - 1: cs = 6; break; - default: cs = 7; break; + if (flags & GP_8BIT) { + if (flags & GP_AFMT) { + switch (cycle_time) { + case 0 ... (1+8) * 510L / 2 - 1: cs = 1; break; + case (1+8) * 510L / 2 ... (8+32) * 510L / 2 - 1: cs = 2; break; + case (8+32) * 510L / 2 ... (32+64) * 510L / 2 - 1: cs = 3; break; + case (32+64) * 510L / 2 ... (64+128) * 510L / 2 - 1: cs = 4; break; + case (64+128) * 510L / 2 ... (128+256) * 510L / 2 - 1: cs = 5; break; + case (128+256) * 510L / 2 ... (256+1024) * 510L / 2 - 1: cs = 6; break; + default: cs = 7; break; + } + } else { + switch (cycle_time) { + case 0 ... (1+8) * 510L / 2 - 1: cs = 1; break; + case (1+8) * 510L / 2 ... (8+64) * 510L / 2 - 1: cs = 2; break; + case (8+64) * 510L / 2 ... (64+256) * 510L / 2 - 1: cs = 3; break; + case (64+256) * 510L / 2 ... (256+1024) * 510L / 2 - 1: cs = 4; break; + default: cs = 5; break; + } } } else { + // 16 Bit timer has enough precision for exact frequency + uint16_t scale; switch (cycle_time) { - case 0 ... (1+8) * 510L / 2 - 1: cs = 1; break; - case (1+8) * 510L / 2 ... (8+64) * 510L / 2 - 1: cs = 2; break; - case (8+64) * 510L / 2 ... (64+256) * 510L / 2 - 1: cs = 3; break; - case (64+256) * 510L / 2 ... (256+1024) * 510L / 2 - 1: cs = 4; break; - default: cs = 5; break; + case 0 ... (8) * 65535L: cs = 1; scale = 1; break; + case (8) * 65535L + 1 ... (64) * 65535L: cs = 2; scale = 8; break; + case (64) * 65535L + 1 ... (256) * 65535L: cs = 3; scale = 64; break; + case (256) * 65535L + 1 ... (1024) * 65535L: cs = 4; scale = 256; break; + default: cs = 5; scale =1024; break; + } + uint16_t rest = cycle_time % scale; + //TODO: check if already programmed + if( cycle_time / scale < 65535) { + *p->icr = rest > 8 ? rest : 8; //Minimum of 8 clock cycles (3 bit) } } + volatile uint8_t *rega = READP(p->rega), *regb = READP(p->regb); uint8_t en_bit = READP(p->en_bit); struct gpio_digital_regs *gpio_regs = GPIO2REGS(pin); @@ -140,6 +161,7 @@ gpio_pwm_write(struct gpio_pwm g, uint16_t val) if (g.size8) { *(volatile uint8_t*)g.reg = val >> 8; // Take the MSB } else { + //TODO: Scale value to "rest" irqstatus_t flag = irq_save(); *(volatile uint16_t*)g.reg = val; irq_restore(flag);