void avr_adc_init(avr_t * avr, avr_adc_t * p) { p->io = _io; avr_register_io(avr, &p->io); avr_register_vector(avr, &p->adc); // allocate this module's IRQ avr_io_setirqs(&p->io, AVR_IOCTL_ADC_GETIRQ, ADC_IRQ_COUNT, NULL); avr_register_io_write(avr, p->r_adcsra, avr_adc_write_adcsra, p); avr_register_io_write(avr, p->r_adcsrb, avr_adc_write_adcsrb, p); avr_register_io_read(avr, p->r_adcl, avr_adc_read_l, p); avr_register_io_read(avr, p->r_adch, avr_adc_read_h, p); }
void avr_spi_init(avr_t * avr, avr_spi_t * p) { p->io = _io; avr_register_io(avr, &p->io); avr_register_vector(avr, &p->spi); // allocate this module's IRQ avr_io_setirqs(&p->io, AVR_IOCTL_SPI_GETIRQ(p->name), SPI_IRQ_COUNT, NULL); avr_register_io_write(avr, p->r_spdr, avr_spi_write, p); avr_register_io_read(avr, p->r_spdr, avr_spi_read, p); }
void avr_twi_init(avr_t * avr, avr_twi_t * p) { p->io = _io; avr_register_io(avr, &p->io); avr_register_vector(avr, &p->twi); //printf("%s TWI%c init\n", __FUNCTION__, p->name); // allocate this module's IRQ avr_io_setirqs(&p->io, AVR_IOCTL_TWI_GETIRQ(p->name), TWI_IRQ_COUNT, NULL); avr_register_io_write(avr, p->twen.reg, avr_twi_write, p); avr_register_io_write(avr, p->r_twdr, avr_twi_write_data, p); avr_register_io_read(avr, p->r_twdr, avr_twi_read_data, p); avr_register_io_write(avr, p->twsr.reg, avr_twi_write_status, p); }
static void avr_timer_reset(avr_io_t * port) { avr_timer_t * p = (avr_timer_t *)port; avr_cycle_timer_cancel(p->io.avr, avr_timer_tov, p); avr_cycle_timer_cancel(p->io.avr, avr_timer_compa, p); avr_cycle_timer_cancel(p->io.avr, avr_timer_compb, p); avr_cycle_timer_cancel(p->io.avr, avr_timer_compc, p); // check to see if the comparators have a pin output. If they do, // (try) to get the ioport corresponding IRQ and connect them // they will automagically be triggered when the comparator raises // it's own IRQ for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) { p->comp[compi].comp_cycles = 0; avr_ioport_getirq_t req = { .bit = p->comp[compi].com_pin }; if (avr_ioctl(port->avr, AVR_IOCTL_IOPORT_GETIRQ_REGBIT, &req) > 0) { // cool, got an IRQ // printf("%s-%c COMP%c Connecting PIN IRQ %d\n", __FUNCTION__, p->name, 'A'+compi, req.irq[0]->irq); avr_connect_irq(&port->irq[TIMER_IRQ_OUT_COMP + compi], req.irq[0]); } } avr_ioport_getirq_t req = { .bit = p->icp }; if (avr_ioctl(port->avr, AVR_IOCTL_IOPORT_GETIRQ_REGBIT, &req) > 0) { // cool, got an IRQ for the input capture pin // printf("%s-%c ICP Connecting PIN IRQ %d\n", __FUNCTION__, p->name, req.irq[0]->irq); avr_irq_register_notify(req.irq[0], avr_timer_irq_icp, p); } } static const char * irq_names[TIMER_IRQ_COUNT] = { [TIMER_IRQ_OUT_PWM0] = "8>pwm0", [TIMER_IRQ_OUT_PWM1] = "8>pwm1", [TIMER_IRQ_OUT_COMP + 0] = ">compa", [TIMER_IRQ_OUT_COMP + 1] = ">compb", [TIMER_IRQ_OUT_COMP + 2] = ">compc", }; static avr_io_t _io = { .kind = "timer", .reset = avr_timer_reset, .irq_names = irq_names, }; void avr_timer_init(avr_t * avr, avr_timer_t * p) { p->io = _io; avr_register_io(avr, &p->io); avr_register_vector(avr, &p->overflow); avr_register_vector(avr, &p->icr); // allocate this module's IRQ avr_io_setirqs(&p->io, AVR_IOCTL_TIMER_GETIRQ(p->name), TIMER_IRQ_COUNT, NULL); // marking IRQs as "filtered" means they don't propagate if the // new value raised is the same as the last one.. in the case of the // pwm value it makes sense not to bother. p->io.irq[TIMER_IRQ_OUT_PWM0].flags |= IRQ_FLAG_FILTERED; p->io.irq[TIMER_IRQ_OUT_PWM1].flags |= IRQ_FLAG_FILTERED; 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); avr_register_io_write(avr, p->cs[0].reg, avr_timer_write, p); // this assumes all the "pending" interrupt bits are in the same // register. Might not be true on all devices ? avr_register_io_write(avr, p->overflow.raised.reg, avr_timer_write_pending, p); /* * Even if the timer is 16 bits, we don't care to have watches on the * high bytes because the datasheet says that the low address is always * the trigger. */ for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) { avr_register_vector(avr, &p->comp[compi].interrupt); if (p->comp[compi].r_ocr) // not all timers have all comparators avr_register_io_write(avr, p->comp[compi].r_ocr, avr_timer_write_ocr, p); } avr_register_io_write(avr, p->r_tcnt, avr_timer_tcnt_write, p); avr_register_io_read(avr, p->r_tcnt, avr_timer_tcnt_read, p); }