From: cskarai Date: Tue, 6 Jan 2015 21:13:40 +0000 (+0100) Subject: Added: free_running autotrigger mode X-Git-Tag: v1.3~57^2~1 X-Git-Url: https://git.htl-mechatronik.at/public/?a=commitdiff_plain;h=70cd616a05fe8333827d569cd5843c81105b8559;p=sx%2Fsimavr.git Added: free_running autotrigger mode --- diff --git a/simavr/sim/avr_adc.c b/simavr/sim/avr_adc.c index a88f335..64fbcd1 100644 --- a/simavr/sim/avr_adc.c +++ b/simavr/sim/avr_adc.c @@ -34,6 +34,8 @@ static avr_cycle_count_t avr_adc_int_raise(struct avr_t * avr, avr_cycle_count_t 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; } @@ -139,8 +141,64 @@ static uint8_t avr_adc_read_h(struct avr_t * avr, avr_io_addr_t addr, void * par } } -static void avr_adc_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) +static void avr_adc_configure_trigger(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) { + avr_adc_t * p = (avr_adc_t *)param; + + uint8_t adate = avr_regbit_get(avr, p->adate); + uint8_t old_adts = p->adts_mode; + + static char * auto_trigger_names[] = { + "none", + "free_running", + "analog_comparator_0", + "analog_comparator_1", + "analog_comparator_2", + "analog_comparator_3", + "external_interrupt_0", + "timer_0_compare_match_a", + "timer_0_compare_match_b", + "timer_0_overflow", + "timer_1_compare_match_b", + "timer_1_overflow", + "timer_1_capture_event", + "pin_change_interrupt", + "psc_module_0_sync_signal", + "psc_module_1_sync_signal", + "psc_module_2_sync_signal", + }; + + if( adate ) + { + uint8_t adts = avr_regbit_get_array(avr, p->adts, ARRAY_SIZE(p->adts)); + p->adts_mode = p->adts_op[adts]; + + switch(p->adts_mode) + { + case avr_adts_free_running: + // do nothing at free running mode + break; + // TODO: implement the other auto trigger modes + default: + AVR_LOG(avr, LOG_WARNING, "ADC: unimplemented auto trigger mode: %s\n", auto_trigger_names[p->adts_mode]); + p->adts_mode = avr_adts_none; + break; + } + } + else + { + // TODO: remove previously configured auto triggers + p->adts_mode = avr_adts_none; + } + + if( old_adts != p->adts_mode ) + AVR_LOG(avr, LOG_TRACE, "ADC: auto trigger configured: %s\n", auto_trigger_names[p->adts_mode]); +} + +static void avr_adc_write_adcsra(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) +{ + avr_adc_configure_trigger(avr, addr, v, param); + avr_adc_t * p = (avr_adc_t *)param; uint8_t adsc = avr_regbit_get(avr, p->adsc); uint8_t aden = avr_regbit_get(avr, p->aden); @@ -188,6 +246,11 @@ static void avr_adc_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, voi avr_core_watch_write(avr, addr, v); } +static void avr_adc_write_adcsrb(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) +{ + avr_adc_configure_trigger(avr, addr, v, param); +} + static void avr_adc_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param) { avr_adc_t * p = (avr_adc_t *)param; @@ -202,7 +265,18 @@ static void avr_adc_irq_notify(struct avr_irq_t * irq, uint32_t value, void * pa } break; case ADC_IRQ_IN_TRIGGER: { if (avr_regbit_get(avr, p->adate)) { - // start a conversion + // start a conversion only if it's not running + // otherwise ignore the trigger + if( ! avr_regbit_get(avr, p->adsc) ) + { + uint8_t addr = p->adsc.reg; + if( addr ) + { + uint8_t val = avr->data[addr] | (1 << p->adsc.bit); + // write ADSC to ADCSRA + avr_adc_write_adcsra(avr, addr, val, param); + } + } } } break; } @@ -257,7 +331,8 @@ void avr_adc_init(avr_t * avr, avr_adc_t * p) // 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, p); + 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); } diff --git a/simavr/sim/avr_adc.h b/simavr/sim/avr_adc.h index 4257312..91247f2 100644 --- a/simavr/sim/avr_adc.h +++ b/simavr/sim/avr_adc.h @@ -82,7 +82,7 @@ enum { // ADC trigger sources typedef enum { - avr_adrs_invalid = 0, + avr_adts_none = 0, avr_adts_free_running, avr_adts_analog_comparator_0, avr_adts_analog_comparator_1, @@ -124,6 +124,7 @@ typedef struct avr_adc_t { uint8_t r_adcsrb; // ADC Control and Status Register B avr_regbit_t adts[4]; // Timing Source avr_adts_type adts_op[16]; // ADTS type + uint8_t adts_mode; // the extracted ADTS mode avr_regbit_t bin; // Bipolar Input Mode (tinyx5 have it) avr_regbit_t ipr; // Input Polarity Reversal (tinyx5 have it)