static void avr_extint_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param) { avr_extint_t * p = (avr_extint_t *)param; avr_t * avr = p->io.avr; uint8_t mode = avr_regbit_get_array(avr, p->eint[irq->irq].isc, 2); int up = !irq->value && value; int down = irq->value && !value; switch (mode) { case 0: // unsupported break; case 1: if (up || down) avr_raise_interrupt(avr, &p->eint[irq->irq].vector); break; case 2: if (down) avr_raise_interrupt(avr, &p->eint[irq->irq].vector); break; case 3: if (up) avr_raise_interrupt(avr, &p->eint[irq->irq].vector); break; } }
static void avr_extint_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param) { avr_extint_t * p = (avr_extint_t *)param; avr_t * avr = p->io.avr; int up = !irq->value && value; int down = irq->value && !value; uint8_t isc_bits = p->eint[irq->irq + 1].isc->reg ? 2 : 1; uint8_t mode = avr_regbit_get_array(avr, p->eint[irq->irq].isc, isc_bits); // Asynchronous interrupts, eg int2 in m16, m32 etc. support only down/up if (isc_bits == 1) mode +=2; switch (mode) { case 0: // unsupported break; case 1: if (up || down) avr_raise_interrupt(avr, &p->eint[irq->irq].vector); break; case 2: if (down) avr_raise_interrupt(avr, &p->eint[irq->irq].vector); break; case 3: if (up) avr_raise_interrupt(avr, &p->eint[irq->irq].vector); break; } }
static avr_cycle_count_t avr_uart_txc_raise(struct avr_t * avr, avr_cycle_count_t when, void * param) { avr_uart_t * p = (avr_uart_t *)param; if (avr_regbit_get(avr, p->txen)) { // if the interrupts are not used, still raise the UDRE and TXC flag avr_raise_interrupt(avr, &p->udrc); avr_raise_interrupt(avr, &p->txc); } return 0; }
// timer overflow static avr_cycle_count_t avr_timer_tov(struct avr_t * avr, avr_cycle_count_t when, void * param) { avr_timer_t * p = (avr_timer_t *)param; int start = p->tov_base == 0; if (!start) avr_raise_interrupt(avr, &p->overflow); p->tov_base = when; static const avr_cycle_timer_t dispatch[AVR_TIMER_COMP_COUNT] = { avr_timer_compa, avr_timer_compb, avr_timer_compc }; for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) { if (p->comp[compi].comp_cycles) { if (p->comp[compi].comp_cycles < p->tov_cycles) avr_cycle_timer_register(avr, p->comp[compi].comp_cycles, dispatch[compi], p); else if (p->tov_cycles == p->comp[compi].comp_cycles && !start) dispatch[compi](avr, when, param); } } return when + p->tov_cycles; }
static avr_cycle_count_t avr_timer_comp(avr_timer_t *p, avr_cycle_count_t when, uint8_t comp) { avr_t * avr = p->io.avr; avr_raise_interrupt(avr, &p->comp[comp].interrupt); // check output compare mode and set/clear pins uint8_t mode = avr_regbit_get(avr, p->comp[comp].com); avr_irq_t * irq = &p->io.irq[TIMER_IRQ_OUT_COMP + comp]; switch (mode) { case avr_timer_com_normal: // Normal mode OCnA disconnected break; case avr_timer_com_toggle: // Toggle OCnA on compare match if (p->comp[comp].com_pin.reg) // we got a physical pin avr_raise_irq(irq, AVR_IOPORT_OUTPUT | (avr_regbit_get(avr, p->comp[comp].com_pin) ? 0 : 1)); else // no pin, toggle the IRQ anyway avr_raise_irq(irq, p->io.irq[TIMER_IRQ_OUT_COMP + comp].value ? 0 : 1); break; case avr_timer_com_clear: avr_raise_irq(irq, 0); break; case avr_timer_com_set: avr_raise_irq(irq, 1); break; } return p->tov_cycles ? 0 : p->comp[comp].comp_cycles ? when + p->comp[comp].comp_cycles : 0; }
static void avr_timer_irq_icp(struct avr_irq_t * irq, uint32_t value, void * param) { avr_timer_t * p = (avr_timer_t *)param; avr_t * avr = p->io.avr; // input capture disabled when ICR is used as top if (p->mode.top == avr_timer_wgm_reg_icr) return; int bing = 0; if (avr_regbit_get(avr, p->ices)) { // rising edge if (!irq->value && value) bing++; } else { // default, falling edge if (irq->value && !value) bing++; } if (!bing) return; // get current TCNT, copy it to ICR, and raise interrupt uint16_t tcnt = _avr_timer_get_current_tcnt(p); avr->data[p->r_icr] = tcnt; if (p->r_icrh) avr->data[p->r_icrh] = tcnt >> 8; avr_raise_interrupt(avr, &p->icr); }
static avr_cycle_count_t avr_uart_rxc_raise(struct avr_t * avr, avr_cycle_count_t when, void * param) { avr_uart_t * p = (avr_uart_t *)param; if (avr_regbit_get(avr, p->rxen)) avr_raise_interrupt(avr, &p->rxc); return 0; }
static avr_cycle_count_t avr_watchdog_timer( struct avr_t * avr, avr_cycle_count_t when, void * param) { avr_watchdog_t * p = (avr_watchdog_t *)param; if (avr_regbit_get(avr, p->watchdog.enable)) { AVR_LOG(avr, LOG_TRACE, "WATCHDOG: timer fired.\n"); avr_raise_interrupt(avr, &p->watchdog); return when + p->cycle_count; } else if (avr_regbit_get(avr, p->wde)) { AVR_LOG(avr, LOG_TRACE, "WATCHDOG: timer fired without interrupt. Resetting\n"); p->reset_context.avr_run = avr->run; p->reset_context.wdrf = 1; /* Ideally we would perform a reset here via 'avr_reset' * However, returning after reset would result in an unconsistent state. * It seems our best (and cleanest) solution is to set a temporary call * back which can safely perform the reset for us... During reset, * the previous callback can be restored and safely resume. */ avr->run = avr_watchdog_run_callback_software_reset; } return 0; }
static void raise_ep_interrupt( struct avr_t * avr, avr_usb_t * p, uint8_t ep, enum epints irq) { struct _epstate * epstate = get_epstate(p, ep); assert(ep < num_endpoints); avr->data[p->r_usbcon + ueint] |= 1 << ep; switch (irq) { case txini: case stalledi: case rxouti: case nakouti: case nakini: epstate->ueintx.v |= 1 << irq; if (epstate->ueienx.v & (1 << irq)) avr_raise_interrupt(avr, &p->state->com_vect); break; case rxstpi: epstate->ueintx.v |= 1 << irq; if (epstate->ueienx.v & (1 << irq)) avr_raise_interrupt(avr, &p->state->com_vect); break; case overfi: epstate->uesta0x.overfi = 1; if (epstate->ueienx.flerre) avr_raise_interrupt(avr, &p->state->com_vect); break; case underfi: epstate->uesta0x.underfi = 1; if (epstate->ueienx.flerre) avr_raise_interrupt(avr, &p->state->com_vect); break; default: assert(0); } }
static avr_cycle_count_t avr_spi_raise(struct avr_t * avr, avr_cycle_count_t when, void * param) { avr_spi_t * p = (avr_spi_t *)param; if (avr_regbit_get(avr, p->spe)) { // in master mode, any byte is sent as it comes.. if (avr_regbit_get(avr, p->mstr)) { avr_raise_interrupt(avr, &p->spi); avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, avr->data[p->r_spdr]); } } return 0; }
static inline void _avr_twi_status_set( avr_twi_t * p, uint8_t v, int interrupt) { avr_regbit_setto_raw(p->io.avr, p->twsr, v); #if AVR_TWI_DEBUG AVR_TRACE(p->io.avr, "%s %02x\n", __func__, v); #endif avr_raise_irq(p->io.irq + TWI_IRQ_STATUS, v); if (interrupt) avr_raise_interrupt(p->io.avr, &p->twi); }
static avr_cycle_count_t avr_watchdog_timer(struct avr_t * avr, avr_cycle_count_t when, void * param) { avr_watchdog_t * p = (avr_watchdog_t *)param; printf("WATCHDOG timer fired.\n"); avr_raise_interrupt(avr, &p->watchdog); if (!avr_regbit_get(avr, p->watchdog.enable)) { printf("WATCHDOG timer fired and interrupt is not enabled. Quitting\n"); avr_sadly_crashed(avr, 10); } return 0; }
static avr_cycle_count_t avr_adc_int_raise(struct avr_t * avr, avr_cycle_count_t when, void * param) { avr_adc_t * p = (avr_adc_t *)param; if (avr_regbit_get(avr, p->aden)) { // if the interrupts are not used, still raised the UDRE and TXC flag avr_raise_interrupt(avr, &p->adc); avr_regbit_clear(avr, p->adsc); p->first = 0; p->read_status = 0; if( p->adts_mode == avr_adts_free_running ) avr_raise_irq(p->io.irq + ADC_IRQ_IN_TRIGGER, 1); } return 0; }
static void avr_spi_irq_input(struct avr_irq_t * irq, uint32_t value, void * param) { avr_spi_t * p = (avr_spi_t *)param; avr_t * avr = p->io.avr; // check to see if receiver is enabled if (!avr_regbit_get(avr, p->spe)) return; // double buffer the input.. ? p->input_data_register = value; avr_raise_interrupt(avr, &p->spi); // if in slave mode, // 'output' the byte only when we received one... if (!avr_regbit_get(avr, p->mstr)) { avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, avr->data[p->r_spdr]); } }
static void raise_usb_interrupt( avr_usb_t * p, enum usbints irq) { uint8_t * Rudien = &p->io.avr->data[p->r_usbcon + udien]; uint8_t * Rudint = &p->io.avr->data[p->r_usbcon + udint]; switch (irq) { case uprsmi: case eorsmi: case wakeupi: case eorsti: case sofi: case suspi: *Rudint |= 1 << irq; if (*Rudien & (1 << irq)) avr_raise_interrupt(p->io.avr, &p->state->gen_vect); break; default: assert(0); } }