/*
Madwizard
Frequentiedeler en pulsvormer
We sturen deze avr aan als een schuifregister: data-bit klaarzetten op PD6 en vervolgens
INT0 even laag en terug hoog maken. Er moeten 20 bit's verzonden worden, eerst 4 bits die de opdracht
bepalen, en vervolgens 16 bits die als data bedoeld zijn.
Als laatste stap: INT1 even laag- en terug hoog maken.
Bereik:
Geen prescaler; maxcnt = 1: F_CPU / 2
Prescaler = 1024; maxcnt = 65535: F_CPU / 67107840
Pros 2007
*/
// Dit moet overeenkomen met de define's in Main.h van Grotendikken
#define PWM 0x02
#define MAXCNT 0x03
#define PRESC 0x04
#include <avr/io.h>
#include <compat/deprecated.h>
#include <avr/interrupt.h>
unsigned int command, data;
unsigned int maxcnt, pwm;
volatile unsigned char tccr1b;
volatile unsigned char vlag;
volatile unsigned long schuifregister;
volatile unsigned long settings;
// Bij het initialiseren starten we de PWM-klok nog niet.
// We wachten op een signaal van Grotendikken.
void init(void)
{
tccr1b = _BV(WGM13) | _BV(WGM12); // Fast PWM; ICR1 = TOP; no CLK
maxcnt = 1000;
pwm = 50;
vlag = 0;
sbi(DDRB, PB3); // PB3 (OC1A) = PWMA-uitgang
sbi(DDRB, PB4); // PB4 (OC1B) = PWMB-uitgang
TCCR1A |= _BV(COM1A1) | _BV(COM1B1) | _BV(WGM11); // Clear AC1A on compare match, set on TOP
TCCR1B |= tccr1b; // Fast PWM, TOP = ICR1
ICR1 = maxcnt; // PWM TOP
OCR1A = maxcnt / 2; // PWM duty cycle A = 50%
OCR1B = pwm; // PWM duty cycle B = variabel
cbi(DDRD, PD2); // PD2 = INT0
sbi(PORTD, PD2); // Pull-up weerstand activeren
cbi(DDRD, PD3); // PD3 = INT1
sbi(PORTD, PD3); // Pull-up weerstand activeren
MCUCR |= _BV(ISC11) | _BV(ISC01);
GIMSK |= _BV(INT0) | _BV(INT1);
cbi(DDRA, PA1); // PD6 = data-ingang
sbi(PORTA, PA1); // Pull-up weerstand activeren
sei(); // Global interrupts on
}
ISR(SIG_INTERRUPT0) // een interrupt op PD2
{
schuifregister = schuifregister << 1; // schuifregister 1 plaatsje naar links
if (bit_is_set(PINA, PINA1)) { // Als PD6 hoog is,
schuifregister |= 0x00000001; // maken we bit 0 van schuifregister hoog
}
}
ISR(SIG_INTERRUPT1) // een interrupt op PD3
{
settings = schuifregister; // Sata-tranfer is compleet
vlag = 1; // Geef een seintje aan main
}
// Met maxcnt = 1 en pwm = 0 is de uitgangsfrequentie gelijk aan de helft v/d CPU_CLK
int main(void)
{
init();
while (1) {
while (vlag == 0) { // Lekker nietsdoen, zolang vlag 0 is...
}
data = settings & 0xFFFF; // Bit 15 ... 0 van settings = data
command = (settings >> 16) & 0x0F; // Bit 19 ... 16 van settings = command
switch (command) {
case PWM: // PWM-verhouding instellen
pwm = data;
if (pwm > maxcnt) {
pwm = maxcnt - 1;
}
OCR1B = pwm;
OCR1A = maxcnt / 2; // PWM duty cycle A = 50%
break;
case MAXCNT: // Max. count instellen
maxcnt = data;
if (maxcnt < pwm) {
maxcnt = pwm + 1;
}
ICR1 = maxcnt;
OCR1A = maxcnt / 2; // PWM duty cycle A = 50%
break;
case PRESC:
tccr1b &= 0xF8; // Bits 0, 1 en 2 van TCCR1B bepalen de CLK-bron
tccr1b |= (unsigned char) (data & 0x07);
TCCR1B = tccr1b;
break;
default:
break;
}
vlag = 0;
}
return 0;
}