40 #include "avrmalloc.h" 66 Timer16Def global_timer16_defs[] = {
68 .timer_name =
"Timer1",
69 .tcnth_name =
"TCNT1H",
70 .tcntl_name =
"TCNT1L",
71 .tccra_name =
"TCCR1A",
72 .tccrb_name =
"TCCR1B",
81 OCReg16Def global_ocreg16_defs[] = {
83 .ocrdev_name =
"OCR1A",
84 .ocrl_name =
"OCR1AL",
85 .ocrh_name =
"OCR1AH",
89 .ocrdev_name =
"OCR1B",
90 .ocrl_name =
"OCR1BL",
91 .ocrh_name =
"OCR1BH",
95 .ocrdev_name =
"OCR1C",
96 .ocrl_name =
"OCR1CL",
97 .ocrh_name =
"OCR1CH",
100 .ocrdev_name =
"OCR3A",
101 .ocrl_name =
"OCR3AL",
102 .ocrh_name =
"OCR3A",
106 .ocrdev_name =
"OCR3B",
107 .ocrl_name =
"OCR3BL",
108 .ocrh_name =
"OCR3BH",
112 .ocrdev_name =
"OCR3C",
113 .ocrl_name =
"OCR3CL",
114 .ocrh_name =
"OCR3CH",
128 static void timer_iadd_addr (VDevice *vdev,
int addr,
char *name,
129 int rel_addr,
void *data);
130 static uint8_t timer_intr_read (VDevice *dev,
int addr);
131 static void timer_intr_write (VDevice *dev,
int addr, uint8_t val);
132 static void timer_intr_reset (VDevice *dev);
133 static int timer_intr_cb (uint64_t time, AvrClass *data);
140 uint8_t *func_mask = (uint8_t *) data;
142 return (VDevice *)timer_intr_new (addr, name, *func_mask);
144 avr_error (
"Attempted timer interrupt create with NULL data pointer");
149 timer_intr_new (
int addr,
char *name, uint8_t func_mask)
170 timer_intr_reset, timer_iadd_addr);
172 ti->func_mask = func_mask;
174 timer_iadd_addr ((VDevice *)ti, addr, name, 0, NULL);
176 timer_intr_reset ((VDevice *)ti);
180 timer_iadd_addr (VDevice *vdev,
int addr,
char *name,
int rel_addr,
183 TimerIntr_T *ti = (TimerIntr_T *)vdev;
185 if (strncmp (
"TIFR", name, 4) == 0)
187 ti->tifr_addr = addr;
190 else if (strncmp (
"TIMSK", name, 5) == 0)
192 ti->timsk_addr = addr;
197 avr_error (
"invalid Timer Interrupt register name: '%s' @ 0x%04x",
214 timer_intr_read (VDevice *dev,
int addr)
216 TimerIntr_T *ti = (TimerIntr_T *)dev;
218 if (addr == ti->timsk_addr)
220 return (ti->timsk & ti->func_mask);
223 else if (addr == ti->tifr_addr)
225 return (ti->tifr & ti->func_mask);
237 timer_intr_write (VDevice *dev,
int addr, uint8_t val)
239 TimerIntr_T *ti = (TimerIntr_T *)dev;
242 if (addr == ti->timsk_addr)
244 ti->timsk = (val & ti->func_mask);
250 else if (ti->intr_cb == NULL)
253 cb = callback_new (timer_intr_cb, (AvrClass *)ti);
259 else if (addr == ti->tifr_addr)
261 ti->tifr &= ~(val & ti->func_mask);
271 timer_intr_reset (VDevice *dev)
273 TimerIntr_T *ti = (TimerIntr_T *)dev;
282 timer_intr_cb (uint64_t time, AvrClass *data)
284 TimerIntr_T *ti = (TimerIntr_T *)data;
285 uint8_t intrs = ti->timsk & ti->tifr & ti->func_mask;
287 if (ti->intr_cb == NULL)
288 return CB_RET_REMOVE;
300 if (intrs & mask_TOV0)
303 ti->tifr &= ~mask_TOV0;
305 else if (intrs & mask_ICF1)
308 ti->tifr &= ~mask_ICF1;
310 else if (intrs & mask_OCF1B)
313 ti->tifr &= ~mask_OCF1B;
315 else if (intrs & mask_OCF1A)
318 ti->tifr &= ~mask_OCF1A;
320 else if (intrs & mask_TOV1)
323 ti->tifr &= ~mask_TOV1;
327 avr_error (
"An invalid interrupt was flagged");
331 return CB_RET_RETAIN;
340 static void timer0_add_addr (VDevice *vdev,
int addr,
char *name,
341 int rel_addr,
void *data);
342 static uint8_t timer0_read (VDevice *dev,
int addr);
343 static void timer0_write (VDevice *dev,
int addr, uint8_t val);
344 static void timer0_reset (VDevice *dev);
345 static int timer0_clk_incr_cb (uint64_t ck, AvrClass *data);
352 return (VDevice *)timer0_new (addr, name, rel_addr);
356 timer0_new (
int addr,
char *name,
int rel_addr)
375 vdev_construct ((VDevice *)timer, timer0_read, timer0_write, timer0_reset,
378 timer0_add_addr ((VDevice *)timer, addr, name, 0, NULL);
380 timer->related_addr = rel_addr;
381 timer0_reset ((VDevice *)timer);
396 timer0_add_addr (VDevice *vdev,
int addr,
char *name,
int rel_addr,
399 Timer0_T *ti = (Timer0_T *)vdev;
401 if (strncmp (
"TCNT", name, 4) == 0)
403 ti->tcnt_addr = addr;
406 else if (strncmp (
"TCCR", name, 4) == 0)
408 ti->tccr_addr = addr;
413 avr_error (
"invalid Timer register name: '%s' @ 0x%04x", name, addr);
418 timer0_read (VDevice *dev,
int addr)
420 Timer0_T *timer = (Timer0_T *)dev;
422 if (addr == timer->tcnt_addr)
425 else if (addr == timer->tccr_addr)
437 timer0_write (VDevice *dev,
int addr, uint8_t val)
439 Timer0_T *timer = (Timer0_T *)dev;
442 if (addr == timer->tcnt_addr)
447 else if (addr == timer->tccr_addr)
457 timer->tccr = val & mask_CS;
463 timer->clk_cb = timer->ext_cb = NULL;
469 avr_error (
"external timer/counter sources is not implemented" 482 timer->divisor = 256;
485 timer->divisor = 1024;
492 timer->ext_cb = NULL;
495 if (timer->clk_cb == NULL)
497 cb = callback_new (timer0_clk_incr_cb, (AvrClass *)timer);
511 timer0_reset (VDevice *dev)
513 Timer0_T *timer = (Timer0_T *)dev;
515 timer->clk_cb = NULL;
516 timer->ext_cb = NULL;
525 timer0_clk_incr_cb (uint64_t ck, AvrClass *data)
527 Timer0_T *timer = (Timer0_T *)data;
528 uint8_t last = timer->tcnt;
534 timer->related_addr);
536 if (timer->clk_cb == NULL)
537 return CB_RET_REMOVE;
539 if (timer->divisor <= 0)
540 avr_error (
"Bad divisor value: %d", timer->divisor);
545 timer->tcnt += ((ck & (timer->divisor - 1)) == 0);
554 if ((timer->tcnt == 0) && (timer->tcnt != last))
555 ti->tifr |= mask_TOV0;
557 return CB_RET_RETAIN;
570 static void timer16_add_addr (VDevice *vdev,
int addr,
char *name,
571 int rel_addr,
void *data);
572 static void timer16_destroy (
void *timer);
573 static uint8_t timer16_read (VDevice *dev,
int addr);
574 static void timer16_write (VDevice *dev,
int addr, uint8_t val);
575 static void timer16_reset (VDevice *dev);
576 static int timer16_clk_incr_cb (uint64_t time, AvrClass *data);
577 static void timer16_handle_tccr_write (Timer16_T *timer);
584 uint8_t *def_data = (uint8_t *) data;
586 return (VDevice *)timer16_new (addr, name, rel_addr,
587 global_timer16_defs[*def_data]);
589 avr_error (
"Attempted timer 16 create with NULL data pointer");
594 timer16_new (
int addr,
char *name,
int rel_addr, Timer16Def timerdef)
598 timer =
avr_new (Timer16_T, 1);
615 timer16_reset, timer16_add_addr);
617 timer->timerdef = timerdef;
619 timer16_add_addr ((VDevice *)timer, addr, name, 0, NULL);
621 timer->related_addr = rel_addr;
622 timer16_reset ((VDevice *)timer);
626 timer16_add_addr (VDevice *vdev,
int addr,
char *name,
int rel_addr,
629 Timer16_T *ti = (Timer16_T *)vdev;
631 if (strncmp (
"TCNTL", name, 5) == 0)
633 ti->tcntl_addr = addr;
636 else if (strncmp (
"TCNTH", name, 5) == 0)
638 ti->tcnth_addr = addr;
641 else if (strncmp (
"TCCRA", name, 5) == 0)
643 ti->tccra_addr = addr;
646 else if (strncmp (
"TCCRB", name, 5) == 0)
648 ti->tccrb_addr = addr;
651 else if (strncmp (
"TCCRC", name, 5) == 0)
653 ti->tccrc_addr = addr;
658 avr_error (
"invalid Timer16 register name: '%s' @ 0x%04x", name,
664 timer16_destroy (
void *timer)
673 timer16_read (VDevice *dev,
int addr)
675 Timer16_T *timer = (Timer16_T *)dev;
677 if (addr == timer->tcntl_addr)
679 timer->TEMP = (uint8_t) ((timer->tcnt) >> 8);
680 return (timer->tcnt) & 0xFF;
683 else if (addr == timer->tcnth_addr)
688 else if (addr == timer->tccra_addr)
693 else if (addr == timer->tccrb_addr)
698 else if (addr == timer->tccrc_addr)
712 timer16_write (VDevice *dev,
int addr, uint8_t val)
714 Timer16_T *timer = (Timer16_T *)dev;
716 if (addr == timer->tcntl_addr)
718 timer->tcnt = (((timer->TEMP) << 8) & 0xFF00) | val;
721 else if (addr == timer->tcnth_addr)
726 else if (addr == timer->tccra_addr)
729 timer16_handle_tccr_write (timer);
732 else if (addr == timer->tccrb_addr)
735 timer16_handle_tccr_write (timer);
738 else if (addr == timer->tccrc_addr)
741 timer16_handle_tccr_write (timer);
751 timer16_reset (VDevice *dev)
753 Timer16_T *timer = (Timer16_T *)dev;
755 timer->clk_cb = NULL;
756 timer->ext_cb = NULL;
767 timer_intr_set_flag (TimerIntr_T *ti, uint8_t bitnr)
773 timer16_clk_incr_cb (uint64_t ck, AvrClass *data)
775 Timer16_T *timer = (Timer16_T *)data;
776 uint16_t last = timer->tcnt;
784 timer->related_addr);
786 if (timer->clk_cb == NULL)
787 return CB_RET_REMOVE;
792 timer->tcnt += ((ck & (timer->divisor - 1)) == 0);
794 if (timer->divisor <= 0)
795 avr_error (
"Bad divisor value: %d", timer->divisor);
799 if (timer->tcnt != last)
802 if (timer->tcnt == 0)
803 timer_intr_set_flag (timer->ti, mask_TOV1);
806 if (timer->ocra && (timer->tcnt == timer->ocra->ocr))
808 timer_intr_set_flag (timer->ti, mask_OCF1A);
811 if (timer->ocrb && (timer->tcnt == timer->ocrb->ocr))
813 timer_intr_set_flag (timer->ti, mask_OCF1B);
816 return CB_RET_RETAIN;
821 timer_intr_clear_flag (TimerIntr_T *ti, uint8_t bitnr)
823 ti->tifr &= ~(bitnr);
828 timer16_handle_tccr_write (Timer16_T *timer)
839 cs = timer->tccrb & 0x07;
845 timer->clk_cb = timer->ext_cb = NULL;
851 avr_error (
"external timer/counter sources is not implemented" 864 timer->divisor = 256;
867 timer->divisor = 1024;
874 timer->ext_cb = NULL;
877 if (timer->clk_cb == NULL)
879 cb = callback_new (timer16_clk_incr_cb, (AvrClass *)timer);
897 static void ocr_add_addr (VDevice *vdev,
int addr,
char *name,
int rel_addr,
899 static void ocreg16_destroy (
void *ocr);
900 static uint8_t ocreg16_read (VDevice *dev,
int addr);
901 static void ocreg16_write (VDevice *dev,
int addr, uint8_t val);
902 static void ocreg16_reset (VDevice *dev);
911 uint8_t *def_data = (uint8_t *) data;
913 return (VDevice *)ocreg16_new (addr, name,
914 global_ocreg16_defs[*def_data]);
916 avr_error (
"Attempted OCReg create with NULL data pointer");
921 ocreg16_new (
int addr,
char *name, OCReg16Def ocrdef)
925 ocreg =
avr_new (OCReg16_T, 1);
941 ocreg16_reset, ocr_add_addr);
943 ocreg->ocrdef = ocrdef;
945 ocr_add_addr ((VDevice *)ocreg, addr, name, 0, NULL);
946 ocreg16_reset ((VDevice *)ocreg);
950 ocr_add_addr (VDevice *vdev,
int addr,
char *name,
int rel_addr,
void *data)
952 OCReg16_T *ocreg = (OCReg16_T *)vdev;
954 if ((strncmp (
"OCRAL", name, 5) == 0) || (strncmp (
"OCRBL", name, 5) == 0)
955 || (strncmp (
"OCRCL", name, 5) == 0))
957 ocreg->ocrl_addr = addr;
960 else if ((strncmp (
"OCRAH", name, 5) == 0)
961 || (strncmp (
"OCRBH", name, 5) == 0)
962 || (strncmp (
"OCRCH", name, 5) == 0))
965 ocreg->ocrh_addr = addr;
970 avr_error (
"invalid Timer16 register name: '%s' @ 0x%04x", name,
976 ocreg16_destroy (
void *ocreg)
985 ocreg16_read (VDevice *dev,
int addr)
987 OCReg16_T *ocreg = (OCReg16_T *)dev;
989 if (addr == ocreg->ocrl_addr)
991 return (ocreg->ocr) & 0xFF;
994 else if (addr == ocreg->ocrh_addr)
996 return (ocreg->ocr) >> 8;
1001 avr_error (
"Bad address: 0x%04x", addr);
1008 ocreg16_write (VDevice *dev,
int addr, uint8_t val)
1010 OCReg16_T *ocreg = (OCReg16_T *)dev;
1012 if (addr == ocreg->ocrl_addr)
1014 ocreg->ocr = (((ocreg->TEMP) << 8) & 0xFF00) | val;
1017 else if (addr == ocreg->ocrh_addr)
1024 avr_error (
"Bad address: 0x%04x", addr);
1029 ocreg16_reset (VDevice *dev)
1031 OCReg16_T *ocreg = (OCReg16_T *)dev;
#define avr_new(type, count)
Macro for allocating memory.
void timer0_construct(Timer0_T *timer, int addr, char *name, int rel_addr)
Constructor for timer/counter 0 object.
void avr_core_async_cb_add(AvrCore *core, CallBack *cb)
Add a new asynchronous callback to list.
VDevice * avr_core_get_vdev_by_addr(AvrCore *core, int addr)
Returns the VDevice which handles the address addr.
void vdev_destroy(void *dev)
Destructor for a VDevice.
VDevice * ocreg16_create(int addr, char *name, int rel_addr, void *data)
Allocate a new 16 bit Output Compare Register.
void timer_intr_destroy(void *ti)
Destructor for timer interrupt object.
void avr_core_irq_raise(AvrCore *core, unsigned int irq)
Raises an irq by adding it's data to the irq_pending list.
AvrClass * vdev_get_core(VDevice *dev)
Get the core field.
VDevice * timer16_create(int addr, char *name, int rel_addr, void *data)
Allocate a new 16 bit timer/counter.
void timer0_destroy(void *timer)
Destructor for timer/counter 0 object.
void vdev_construct(VDevice *dev, VDevFP_Read rd, VDevFP_Write wr, VDevFP_Reset reset, VDevFP_AddAddr add_addr)
Constructor for a VDevice.
#define avr_error(fmt, args...)
Print an error message to stderr and terminate program.
void timer16_construct(Timer16_T *timer, int addr, char *name, int rel_addr, Timer16Def timerdef)
Constructor for 16 bit timer/counter object.
VDevice * timer0_create(int addr, char *name, int rel_addr, void *data)
Allocate a new timer/counter 0.
void ocreg16_construct(OCReg16_T *ocreg, int addr, char *name, OCReg16Def ocrdef)
Constructor for 16 bit Output Compare Register object.
void avr_core_clk_cb_add(AvrCore *core, CallBack *cb)
Add a new clock callback to list.
void timer_intr_construct(TimerIntr_T *ti, int addr, char *name, uint8_t func_mask)
Constructor for timer interrupt object.
void class_overload_destroy(AvrClass *klass, AvrClassFP_Destroy destroy)
Overload the default destroy method.
VDevice * timer_int_create(int addr, char *name, int rel_addr, void *data)
Allocate a new timer interrupt.