Main Page | File List | Globals | Related Pages

timers.c

Go to the documentation of this file.
00001 /* 00002 * $Id: timers.c,v 1.13 2003/12/02 08:25:00 troth Exp $ 00003 * 00004 **************************************************************************** 00005 * 00006 * simulavr - A simulator for the Atmel AVR family of microcontrollers. 00007 * Copyright (C) 2001, 2002, 2003 Theodore A. Roth 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 * 00023 **************************************************************************** 00024 */ 00025 00026 /** 00027 * \file timers.c 00028 * \brief Module to simulate the AVR's on-board timer/counters. 00029 * 00030 * This currently only implements the timer/counter 0. 00031 */ 00032 00033 #include <config.h> 00034 00035 #include <stdio.h> 00036 #include <stdlib.h> 00037 00038 #include "avrerror.h" 00039 #include "avrmalloc.h" 00040 #include "avrclass.h" 00041 #include "utils.h" 00042 #include "callback.h" 00043 #include "op_names.h" 00044 00045 #include "storage.h" 00046 #include "flash.h" 00047 00048 #include "vdevs.h" 00049 #include "memory.h" 00050 #include "stack.h" 00051 #include "register.h" 00052 #include "sram.h" 00053 #include "eeprom.h" 00054 #include "timers.h" 00055 #include "ports.h" 00056 00057 #include "avrcore.h" 00058 00059 #include "intvects.h" 00060 00061 #ifndef DOXYGEN 00062 00063 Timer16Def global_timer16_defs[] = { 00064 { 00065 .timer_name = "Timer1", 00066 .tcnth_name = "TCNT1H", 00067 .tcntl_name = "TCNT1L", 00068 .tccra_name = "TCCR1A", 00069 .tccrb_name = "TCCR1B", 00070 .base = 0x4c, 00071 .tof = bit_TOV1, 00072 .ocf_a = bit_OCF1A, 00073 .ocf_b = bit_OCF1B, 00074 .ocf_c = 8} 00075 }; 00076 00077 OCReg16Def global_ocreg16_defs[] = { 00078 { 00079 .ocrdev_name = "OCR1A", 00080 .ocrl_name = "OCR1AL", 00081 .ocrh_name = "OCR1AH", 00082 .base = 0x4a}, 00083 { 00084 .ocrdev_name = "OCR1B", 00085 .ocrl_name = "OCR1BL", 00086 .ocrh_name = "OCR1BH", 00087 .base = 0x48}, 00088 { 00089 .ocrdev_name = "OCR1C", 00090 .ocrl_name = "OCR1CL", 00091 .ocrh_name = "OCR1CH", 00092 .base = 0x78}, 00093 { 00094 .ocrdev_name = "OCR3A", 00095 .ocrl_name = "OCR3AL", 00096 .ocrh_name = "OCR3A", 00097 .base = 0x86}, 00098 { 00099 .ocrdev_name = "OCR3B", 00100 .ocrl_name = "OCR3BL", 00101 .ocrh_name = "OCR3BH", 00102 .base = 0x84}, 00103 { 00104 .ocrdev_name = "OCR3C", 00105 .ocrl_name = "OCR3CL", 00106 .ocrh_name = "OCR3CH", 00107 .base = 0x82} 00108 }; 00109 00110 #endif /* not DOXYGEN */ 00111 00112 /****************************************************************************\ 00113 * 00114 * Timer/Counter 0 00115 * 00116 \****************************************************************************/ 00117 00118 static uint8_t timer_intr_read (VDevice *dev, int addr); 00119 static void timer_intr_write (VDevice *dev, int addr, uint8_t val); 00120 static void timer_intr_reset (VDevice *dev); 00121 static char *timer_intr_reg_name (VDevice *dev, int addr); 00122 static int timer_intr_cb (uint64_t time, AvrClass *data); 00123 00124 /** \brief Allocate a new timer interrupt */ 00125 00126 TimerIntr_T * 00127 timer_intr_new (uint8_t func_mask) 00128 { 00129 TimerIntr_T *ti; 00130 00131 ti = avr_new (TimerIntr_T, 1); 00132 timer_intr_construct (ti, func_mask); 00133 class_overload_destroy ((AvrClass *)ti, timer_intr_destroy); 00134 00135 return ti; 00136 } 00137 00138 /** \brief Constructor for timer interrupt object. */ 00139 00140 void 00141 timer_intr_construct (TimerIntr_T *ti, uint8_t func_mask) 00142 { 00143 char *name = "TimerIntr"; 00144 00145 if (ti == NULL) 00146 avr_error ("passed null ptr"); 00147 00148 vdev_construct ((VDevice *)ti, name, TIMER_INTR_BASE, TIMER_INTR_SIZE, 00149 timer_intr_read, timer_intr_write, timer_intr_reset, 00150 timer_intr_reg_name); 00151 00152 ti->func_mask = func_mask; 00153 00154 timer_intr_reset ((VDevice *)ti); 00155 } 00156 00157 /** \brief Destructor for timer interrupt object. */ 00158 00159 void 00160 timer_intr_destroy (void *ti) 00161 { 00162 if (ti == NULL) 00163 return; 00164 00165 vdev_destroy (ti); 00166 } 00167 00168 static uint8_t 00169 timer_intr_read (VDevice *dev, int addr) 00170 { 00171 TimerIntr_T *ti = (TimerIntr_T *)dev; 00172 00173 switch (addr - vdev_get_base (dev)) 00174 { 00175 case TIMER_INTR_TIMSK_ADDR: 00176 return (ti->timsk & ti->func_mask); 00177 case TIMER_INTR_TIFR_ADDR: 00178 return (ti->tifr & ti->func_mask); 00179 default: 00180 avr_error ("Bad address: 0x%04x", addr); 00181 } 00182 return 0; /* will never get here */ 00183 } 00184 00185 static void 00186 timer_intr_write (VDevice *dev, int addr, uint8_t val) 00187 { 00188 TimerIntr_T *ti = (TimerIntr_T *)dev; 00189 int offset = addr - vdev_get_base (dev); 00190 CallBack *cb; 00191 00192 if (offset == TIMER_INTR_TIMSK_ADDR) 00193 { 00194 ti->timsk = (val & ti->func_mask); 00195 if (ti->timsk == 0) 00196 { 00197 ti->intr_cb = NULL; /* no interrupt are enabled, remove the 00198 callback */ 00199 } 00200 else if (ti->intr_cb == NULL) 00201 { 00202 /* we need to install the intr_cb function */ 00203 cb = callback_new (timer_intr_cb, (AvrClass *)ti); 00204 ti->intr_cb = cb; 00205 avr_core_async_cb_add ((AvrCore *)vdev_get_core (dev), cb); 00206 } 00207 } 00208 else if (offset == TIMER_INTR_TIFR_ADDR) 00209 { 00210 ti->tifr = (val & ti->func_mask); 00211 } 00212 else 00213 { 00214 avr_error ("Bad address: 0x%04x", addr); 00215 } 00216 } 00217 00218 static void 00219 timer_intr_reset (VDevice *dev) 00220 { 00221 TimerIntr_T *ti = (TimerIntr_T *)dev; 00222 00223 ti->intr_cb = NULL; 00224 00225 ti->timsk = 0; 00226 ti->tifr = 0; 00227 } 00228 00229 static char * 00230 timer_intr_reg_name (VDevice *dev, int addr) 00231 { 00232 switch (addr - vdev_get_base (dev)) 00233 { 00234 case TIMER_INTR_TIMSK_ADDR: 00235 return "TIMSK"; 00236 case TIMER_INTR_TIFR_ADDR: 00237 return "TIFR"; 00238 default: 00239 avr_error ("Bad address: 0x%04x", addr); 00240 } 00241 return NULL; /* will never get here */ 00242 } 00243 00244 static int 00245 timer_intr_cb (uint64_t time, AvrClass *data) 00246 { 00247 TimerIntr_T *ti = (TimerIntr_T *)data; 00248 uint8_t intrs = ti->timsk & ti->tifr & ti->func_mask; 00249 00250 if (ti->intr_cb == NULL) 00251 return CB_RET_REMOVE; 00252 00253 if (intrs) 00254 { 00255 AvrCore *core = (AvrCore *)vdev_get_core ((VDevice *)ti); 00256 00257 /* 00258 * FIXME: Once an irq has been raised, the flag should be cleared, 00259 * _BUT_ should it be done here? Might be a problem if there are 00260 * many interrupts pending and then the user wants to clear one. 00261 */ 00262 00263 if (intrs & mask_TOV0) 00264 { 00265 avr_core_irq_raise (core, irq_vect_table_index (TIMER0_OVF)); 00266 ti->tifr &= ~mask_TOV0; 00267 } 00268 else if (intrs & mask_ICF1) 00269 { 00270 avr_core_irq_raise (core, irq_vect_table_index (TIMER1_CAPT)); 00271 ti->tifr &= ~mask_ICF1; 00272 } 00273 else if (intrs & mask_OCF1B) 00274 { 00275 avr_core_irq_raise (core, irq_vect_table_index (TIMER1_COMPB)); 00276 ti->tifr &= ~mask_OCF1B; 00277 } 00278 else if (intrs & mask_OCF1A) 00279 { 00280 avr_core_irq_raise (core, irq_vect_table_index (TIMER1_COMPA)); 00281 ti->tifr &= ~mask_OCF1A; 00282 } 00283 else if (intrs & mask_TOV1) 00284 { 00285 avr_core_irq_raise (core, irq_vect_table_index (TIMER1_OVF)); 00286 ti->tifr &= ~mask_TOV1; 00287 } 00288 else 00289 { 00290 avr_error ("An invalid interrupt was flagged"); 00291 } 00292 } 00293 00294 return CB_RET_RETAIN; 00295 } 00296 00297 /****************************************************************************\ 00298 * 00299 * Timer/Counter 0 00300 * 00301 \****************************************************************************/ 00302 00303 static uint8_t timer0_read (VDevice *dev, int addr); 00304 static void timer0_write (VDevice *dev, int addr, uint8_t val); 00305 static void timer0_reset (VDevice *dev); 00306 static char *timer0_reg_name (VDevice *dev, int addr); 00307 static int timer0_clk_incr_cb (uint64_t ck, AvrClass *data); 00308 00309 /** \brief Allocate a new timer/counter 0. */ 00310 00311 Timer0_T * 00312 timer0_new (void) 00313 { 00314 Timer0_T *timer; 00315 00316 timer = avr_new (Timer0_T, 1); 00317 timer0_construct (timer); 00318 class_overload_destroy ((AvrClass *)timer, timer0_destroy); 00319 00320 return timer; 00321 } 00322 00323 /** \brief Constructor for timer/counter 0 object. */ 00324 00325 void 00326 timer0_construct (Timer0_T *timer) 00327 { 00328 char *name = "Timer0"; 00329 00330 if (timer == NULL) 00331 avr_error ("passed null ptr"); 00332 00333 vdev_construct ((VDevice *)timer, name, TIMER0_BASE, TIMER0_SIZE, 00334 timer0_read, timer0_write, timer0_reset, timer0_reg_name); 00335 00336 timer0_reset ((VDevice *)timer); 00337 } 00338 00339 /** \brief Destructor for timer/counter 0 object. */ 00340 00341 void 00342 timer0_destroy (void *timer) 00343 { 00344 if (timer == NULL) 00345 return; 00346 00347 vdev_destroy (timer); 00348 } 00349 00350 static uint8_t 00351 timer0_read (VDevice *dev, int addr) 00352 { 00353 Timer0_T *timer = (Timer0_T *)dev; 00354 00355 switch (addr - vdev_get_base (dev)) 00356 { 00357 case TIMER0_TCNT_ADDR: 00358 return timer->tcnt; 00359 case TIMER0_TCCR_ADDR: 00360 return timer->tccr; 00361 default: 00362 avr_error ("Bad address: 0x%04x", addr); 00363 } 00364 return 0; /* will never get here */ 00365 } 00366 00367 static void 00368 timer0_write (VDevice *dev, int addr, uint8_t val) 00369 { 00370 Timer0_T *timer = (Timer0_T *)dev; 00371 int offset = addr - vdev_get_base (dev); 00372 CallBack *cb; 00373 00374 if (offset == TIMER0_TCNT_ADDR) 00375 { 00376 timer->tcnt = val; 00377 } 00378 else if (offset == TIMER0_TCCR_ADDR) 00379 { 00380 /* 00381 * When the user writes toe TCCR, a callback is installed for either 00382 * clock generated increments or externally generated increments. The 00383 * two incrememtor callback are mutally exclusive, only one or the 00384 * other can be installed at any given instant. 00385 */ 00386 00387 /* timer 0 only has clock select function. */ 00388 timer->tccr = val & mask_CS; 00389 00390 switch (timer->tccr) 00391 { 00392 case CS_STOP: 00393 /* stop either of the installed callbacks */ 00394 timer->clk_cb = timer->ext_cb = NULL; 00395 timer->divisor = 0; 00396 return; 00397 case CS_EXT_FALL: 00398 case CS_EXT_RISE: 00399 /* FIXME: not implemented yet */ 00400 avr_error ("external timer/counter sources is not implemented" 00401 " yet"); 00402 return; 00403 case CS_CK: 00404 timer->divisor = 1; 00405 break; 00406 case CS_CK_8: 00407 timer->divisor = 8; 00408 break; 00409 case CS_CK_64: 00410 timer->divisor = 64; 00411 break; 00412 case CS_CK_256: 00413 timer->divisor = 256; 00414 break; 00415 case CS_CK_1024: 00416 timer->divisor = 1024; 00417 break; 00418 default: 00419 avr_error ("The impossible happened!"); 00420 } 00421 /* remove external incrementor if installed */ 00422 if (timer->ext_cb) 00423 timer->ext_cb = NULL; 00424 00425 /* install the clock incrementor callback (with flair!) */ 00426 if (timer->clk_cb == NULL) 00427 { 00428 cb = callback_new (timer0_clk_incr_cb, (AvrClass *)timer); 00429 timer->clk_cb = cb; 00430 avr_core_clk_cb_add ((AvrCore *)vdev_get_core ((VDevice *)timer), 00431 cb); 00432 } 00433 } 00434 else 00435 { 00436 avr_error ("Bad address: 0x%04x", addr); 00437 } 00438 } 00439 00440 static void 00441 timer0_reset (VDevice *dev) 00442 { 00443 Timer0_T *timer = (Timer0_T *)dev; 00444 00445 timer->clk_cb = NULL; 00446 timer->ext_cb = NULL; 00447 00448 timer->tccr = 0; 00449 timer->tcnt = 0; 00450 00451 timer->divisor = 0; 00452 } 00453 00454 static char * 00455 timer0_reg_name (VDevice *dev, int addr) 00456 { 00457 switch (addr - vdev_get_base (dev)) 00458 { 00459 case TIMER0_TCNT_ADDR: 00460 return "TCNT0"; 00461 case TIMER0_TCCR_ADDR: 00462 return "TCCR0"; 00463 default: 00464 avr_error ("Bad address: 0x%04x", addr); 00465 } 00466 return NULL; 00467 } 00468 00469 static int 00470 timer0_clk_incr_cb (uint64_t ck, AvrClass *data) 00471 { 00472 Timer0_T *timer = (Timer0_T *)data; 00473 uint8_t last = timer->tcnt; 00474 TimerIntr_T *ti; 00475 00476 ti = (TimerIntr_T *)avr_core_get_vdev_by_name ((AvrCore *) 00477 vdev_get_core ((VDevice *) 00478 timer), 00479 "TimerIntr"); 00480 00481 if (timer->clk_cb == NULL) 00482 return CB_RET_REMOVE; 00483 00484 if (timer->divisor <= 0) 00485 avr_error ("Bad divisor value: %d", timer->divisor); 00486 00487 /* Increment clock if ck is a mutliple of divisor. Since divisor is always 00488 a power of 2, it's much faster to do the bitwise AND instead of using 00489 the integer modulus operator (%). */ 00490 timer->tcnt += ((ck & (timer->divisor - 1)) == 0); 00491 00492 /* Check if tcnt rolled over and if so, set the overflow flag. If 00493 overflow interrupts are set? what if they aren't? This is set 00494 irregardless of whether SREG-I or TOIE0 are set (overflow interrupt 00495 enabled) and thus allows the interrupt to be pending until manually 00496 cleared (writing a one to the TOV0 flag) or interrupts are enabled. My 00497 interpretation of the datasheets. See datasheet discussion of TIFR. 00498 TRoth */ 00499 if ((timer->tcnt == 0) && (timer->tcnt != last)) 00500 ti->tifr |= mask_TOV0; 00501 00502 return CB_RET_RETAIN; 00503 } 00504 00505 /****************************************************************************\ 00506 * 00507 * Timer/Counter 1/3 (16 bit) 00508 * 00509 \****************************************************************************/ 00510 00511 /** \name 16 Bit Timer Functions */ 00512 00513 /*@{*/ 00514 00515 static void timer16_destroy (void *timer); 00516 static uint8_t timer16_read (VDevice *dev, int addr); 00517 static void timer16_write (VDevice *dev, int addr, uint8_t val); 00518 static void timer16_reset (VDevice *dev); 00519 static char *timer16_reg_name (VDevice *dev, int addr); 00520 static int timer16_clk_incr_cb (uint64_t time, AvrClass *data); 00521 static void timer16_handle_tccr_write (Timer16_T *timer); 00522 00523 /** \brief Allocate a new 16 bit timer/counter. */ 00524 00525 Timer16_T * 00526 timer16_new (Timer16Def timerdef) 00527 { 00528 Timer16_T *timer; 00529 00530 timer = avr_new (Timer16_T, 1); 00531 timer16_construct (timer, timerdef); 00532 class_overload_destroy ((AvrClass *)timer, timer16_destroy); 00533 00534 return timer; 00535 } 00536 00537 /** \brief Constructor for 16 bit timer/counter object. */ 00538 00539 void 00540 timer16_construct (Timer16_T *timer, Timer16Def timerdef) 00541 { 00542 char *name = "Timer16"; 00543 00544 if (timer == NULL) 00545 avr_error ("passed null ptr"); 00546 00547 vdev_construct ((VDevice *)timer, name, TIMER16_BASE, TIMER16_SIZE, 00548 timer16_read, timer16_write, timer16_reset, 00549 timer16_reg_name); 00550 00551 timer->timerdef = timerdef; 00552 00553 timer16_reset ((VDevice *)timer); 00554 } 00555 00556 static void 00557 timer16_destroy (void *timer) 00558 { 00559 if (timer == NULL) 00560 return; 00561 00562 vdev_destroy (timer); 00563 } 00564 00565 static uint8_t 00566 timer16_read (VDevice *dev, int addr) 00567 { 00568 Timer16_T *timer = (Timer16_T *)dev; 00569 00570 switch (addr - vdev_get_base (dev)) 00571 { 00572 case TCNTL_ADDR: 00573 timer->TEMP = (uint8_t) ((timer->tcnt) >> 8); 00574 return (timer->tcnt) & 0xFF; 00575 case TCNTH_ADDR: 00576 return timer->TEMP; 00577 case TCCRA_ADDR: 00578 return (timer->tccr) & 0xFF; 00579 case TCCRB_ADDR: 00580 return (timer->tccr) >> 8; 00581 /* FIXME: Need TCCRC for mega128/64 and maybe others. */ 00582 default: 00583 avr_error ("Bad address: 0x%04x", addr); 00584 } 00585 return 0; /* will never get here */ 00586 } 00587 00588 static void 00589 timer16_write (VDevice *dev, int addr, uint8_t val) 00590 { 00591 Timer16_T *timer = (Timer16_T *)dev; 00592 int offset = addr - vdev_get_base (dev); 00593 00594 switch (offset) 00595 { 00596 case TCNTL_ADDR: 00597 timer->tcnt = (((timer->TEMP) << 8) & 0xFF00) | val; 00598 break; 00599 case TCNTH_ADDR: 00600 timer->TEMP = val; 00601 break; 00602 case TCCRA_ADDR: 00603 timer->tccr = (timer->tccr & 0xFF00) | val; 00604 timer16_handle_tccr_write (timer); 00605 break; 00606 case TCCRB_ADDR: 00607 timer->tccr = (timer->tccr & 0xFF) | (val << 8); 00608 timer16_handle_tccr_write (timer); 00609 break; 00610 /* FIXME: Need TCCRC for mega128/64 and maybe others. */ 00611 default: 00612 avr_error ("Bad address: 0x%04x", addr); 00613 } 00614 } 00615 00616 static void 00617 timer16_reset (VDevice *dev) 00618 { 00619 Timer16_T *timer = (Timer16_T *)dev; 00620 00621 timer->clk_cb = NULL; 00622 timer->ext_cb = NULL; 00623 00624 timer->tccr = 0; 00625 timer->tcnt = 0; 00626 00627 timer->divisor = 0; 00628 } 00629 00630 static char * 00631 timer16_reg_name (VDevice *dev, int addr) 00632 { 00633 switch (addr - vdev_get_base (dev)) 00634 { 00635 case TCNTL_ADDR: 00636 return "TCNT1L"; 00637 case TCNTH_ADDR: 00638 return "TCNT1H"; 00639 case TCCRA_ADDR: 00640 return "TCCR1A"; 00641 case TCCRB_ADDR: 00642 return "TCCR1B"; 00643 default: 00644 avr_error ("Bad address: 0x%04x", addr); 00645 } 00646 return NULL; 00647 } 00648 00649 static void 00650 timer_intr_set_flag (TimerIntr_T *ti, uint8_t bitnr) 00651 { 00652 ti->tifr |= bitnr; 00653 } 00654 00655 static int 00656 timer16_clk_incr_cb (uint64_t ck, AvrClass *data) 00657 { 00658 Timer16_T *timer = (Timer16_T *)data; 00659 uint16_t last = timer->tcnt; 00660 00661 if (!timer->ti) 00662 timer->ti = 00663 (TimerIntr_T *)avr_core_get_vdev_by_name ((AvrCore *) 00664 vdev_get_core ((VDevice 00665 *) 00666 timer), 00667 "TimerIntr"); 00668 00669 if (timer->clk_cb == NULL) 00670 return CB_RET_REMOVE; 00671 00672 /* Increment clock if ck is a mutliple of divisor. Since divisor is always 00673 a power of 2, it's much faster to do the bitwise AND instead of using 00674 the integer modulus operator (%). */ 00675 timer->tcnt += ((ck & (timer->divisor - 1)) == 0); 00676 00677 if (timer->divisor <= 0) 00678 avr_error ("Bad divisor value: %d", timer->divisor); 00679 00680 /* The following things only have to be checked if the counter value has 00681 changed */ 00682 if (timer->tcnt != last) 00683 { 00684 /* An overflow occurred */ 00685 if (timer->tcnt == 0) 00686 timer_intr_set_flag (timer->ti, mask_TOV1); 00687 00688 /* The counter value matches one of the ocr values */ 00689 if (timer->ocra && (timer->tcnt == timer->ocra->ocr)) 00690 { 00691 timer_intr_set_flag (timer->ti, mask_OCF1A); 00692 } 00693 00694 if (timer->ocrb && (timer->tcnt == timer->ocrb->ocr)) 00695 { 00696 timer_intr_set_flag (timer->ti, mask_OCF1B); 00697 } 00698 } 00699 return CB_RET_RETAIN; 00700 } 00701 00702 #if 0 00703 static void 00704 timer_intr_clear_flag (TimerIntr_T *ti, uint8_t bitnr) 00705 { 00706 ti->tifr &= ~(bitnr); 00707 } 00708 #endif 00709 00710 static void 00711 timer16_handle_tccr_write (Timer16_T *timer) 00712 { 00713 int cs; 00714 CallBack *cb; 00715 /* 00716 * When the user writes toe TCCR, a callback is installed for either 00717 * clock generated increments or externally generated increments. The 00718 * two incrememtor callback are mutally exclusive, only one or the 00719 * other can be installed at any given instant. 00720 */ 00721 00722 cs = ((timer->tccr) >> 8) & 0x07; 00723 00724 switch (cs) 00725 { 00726 case CS_STOP: 00727 /* stop either of the installed callbacks */ 00728 timer->clk_cb = timer->ext_cb = NULL; 00729 timer->divisor = 0; 00730 return; 00731 case CS_EXT_FALL: 00732 case CS_EXT_RISE: 00733 /* FIXME: not implemented yet */ 00734 avr_error ("external timer/counter sources is not implemented" 00735 "yet"); 00736 return; 00737 case CS_CK: 00738 timer->divisor = 1; 00739 break; 00740 case CS_CK_8: 00741 timer->divisor = 8; 00742 break; 00743 case CS_CK_64: 00744 timer->divisor = 64; 00745 break; 00746 case CS_CK_256: 00747 timer->divisor = 256; 00748 break; 00749 case CS_CK_1024: 00750 timer->divisor = 1024; 00751 break; 00752 default: 00753 avr_error ("The impossible happened!"); 00754 } 00755 /* remove external incrementor if installed */ 00756 if (timer->ext_cb) 00757 timer->ext_cb = NULL; 00758 00759 /* install the clock incrementor callback (with flair!) */ 00760 if (timer->clk_cb == NULL) 00761 { 00762 cb = callback_new (timer16_clk_incr_cb, (AvrClass *)timer); 00763 timer->clk_cb = cb; 00764 avr_core_clk_cb_add ((AvrCore *)vdev_get_core ((VDevice *)timer), cb); 00765 } 00766 } 00767 00768 /*@}*/ 00769 00770 /****************************************************************************\ 00771 * 00772 * Timer16OCR(VDevice) : 16bit - Timer/Counter - Output Compare Register 00773 * 00774 \****************************************************************************/ 00775 00776 /** \name 16 Bit Output Compare Register Functions */ 00777 00778 /*@{*/ 00779 00780 static void ocreg16_destroy (void *ocr); 00781 static uint8_t ocreg16_read (VDevice *dev, int addr); 00782 static void ocreg16_write (VDevice *dev, int addr, uint8_t val); 00783 static void ocreg16_reset (VDevice *dev); 00784 static char *ocreg16_reg_name (VDevice *dev, int addr); 00785 00786 /** \brief Allocate a new 16 bit Output Compare Register 00787 * \param ocrdef The definition struct for the \a OCR to be created 00788 */ 00789 00790 OCReg16_T * 00791 ocreg16_new (OCReg16Def ocrdef) 00792 { 00793 OCReg16_T *ocreg; 00794 00795 ocreg = avr_new (OCReg16_T, 1); 00796 ocreg16_construct (ocreg, ocrdef); 00797 class_overload_destroy ((AvrClass *)ocreg, ocreg16_destroy); 00798 00799 return ocreg; 00800 } 00801 00802 /** \brief Constructor for 16 bit Output Compare Register object. */ 00803 00804 void 00805 ocreg16_construct (OCReg16_T *ocreg, OCReg16Def ocrdef) 00806 { 00807 if (ocreg == NULL) 00808 avr_error ("passed null ptr"); 00809 00810 vdev_construct ((VDevice *)ocreg, ocrdef.ocrdev_name, ocrdef.base, 00811 OCREG16_SIZE, ocreg16_read, ocreg16_write, ocreg16_reset, 00812 ocreg16_reg_name); 00813 00814 ocreg->ocrdef = ocrdef; 00815 00816 ocreg16_reset ((VDevice *)ocreg); 00817 } 00818 00819 static void 00820 ocreg16_destroy (void *ocreg) 00821 { 00822 if (ocreg == NULL) 00823 return; 00824 00825 vdev_destroy (ocreg); 00826 } 00827 00828 static uint8_t 00829 ocreg16_read (VDevice *dev, int addr) 00830 { 00831 OCReg16_T *ocreg = (OCReg16_T *)dev; 00832 00833 switch (addr - vdev_get_base (dev)) 00834 { 00835 case OCRL_ADDR: 00836 return (ocreg->ocr) & 0xFF; 00837 case OCRH_ADDR: 00838 return (ocreg->ocr) >> 8; 00839 default: 00840 avr_error ("Bad address: 0x%04x", addr); 00841 } 00842 return 0; 00843 } 00844 00845 static void 00846 ocreg16_write (VDevice *dev, int addr, uint8_t val) 00847 { 00848 OCReg16_T *ocreg = (OCReg16_T *)dev; 00849 00850 switch (addr - vdev_get_base (dev)) 00851 { 00852 case OCRL_ADDR: 00853 ocreg->ocr = (((ocreg->TEMP) << 8) & 0xFF00) | val; 00854 break; 00855 case OCRH_ADDR: 00856 ocreg->TEMP = val; 00857 break; 00858 default: 00859 avr_error ("Bad address: 0x%04x", addr); 00860 } 00861 } 00862 00863 static void 00864 ocreg16_reset (VDevice *dev) 00865 { 00866 OCReg16_T *ocreg = (OCReg16_T *)dev; 00867 00868 ocreg->ocr = 0; 00869 } 00870 00871 static char * 00872 ocreg16_reg_name (VDevice *dev, int addr) 00873 { 00874 OCReg16_T *ocreg = (OCReg16_T *)dev; 00875 00876 switch (addr - vdev_get_base (dev)) 00877 { 00878 case OCRL_ADDR: 00879 return ocreg->ocrdef.ocrl_name; 00880 case OCRH_ADDR: 00881 return ocreg->ocrdef.ocrh_name; 00882 default: 00883 avr_error ("Bad address: 0x%04x", addr); 00884 } 00885 return 0; 00886 } 00887 00888 /*@}*/

Automatically generated by Doxygen 1.3.8 on 11 Aug 2004.