source: buchla-emu/emu/tim.c@ 212bc4c

Last change on this file since 212bc4c was 212bc4c, checked in by Alexander Heinrich <alex.heinrich@…>, 7 years ago

Add rudimentary timer

Add rudimentary timer that responds to the bios read and write requests
and sends an interrupt, if it has counted to 0.

  • Property mode set to 100644
File size: 2.6 KB
Line 
1/*
2 * Copyright (C) 2017 The Contributors
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or (at
7 * your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * A copy of the GNU General Public License can be found in the file
15 * "gpl.txt" in the top directory of this repository.
16 */
17
18#include <all.h>
19
20#define ver(...) _ver(tim_verbose, 0, __VA_ARGS__)
21#define ver2(...) _ver(tim_verbose, 1, __VA_ARGS__)
22#define ver3(...) _ver(tim_verbose, 2, __VA_ARGS__)
23
24typedef struct {
25 uint32_t irq;
26 bool run;
27 uint32_t latch;
28 uint32_t count;
29} state_timer;
30
31static state_timer timers[] = {
32 {.irq = 0, .run = false, .latch = 32, .count = 32},
33 {.irq = 0, .run = false, .latch = 3200, .count = 3200},
34 {.irq = 0, .run = false, .latch = 801, .count = 801}
35};
36
37#define REG_CRX 0
38#define REG_CR2 1
39#define REG_T1H 2
40#define REG_T1L 3
41#define REG_T2H 4
42#define REG_T2L 5
43#define REG_T3H 6
44#define REG_T3L 7
45
46int32_t tim_verbose = 0;
47
48void tim_init(void)
49{
50 ver("tim init");
51}
52
53void tim_quit(void)
54{
55 ver("tim quit");
56}
57
58bool tim_exec(void)
59{
60 for (int32_t i = 0; i < ARRAY_COUNT(timers); ++i) {
61 if(timers[i].run == true) {
62 --timers[i].count;
63 if(timers[i].count == 0) {
64 timers[i].count = timers[i].latch;
65 timers[i].irq = 1;
66 }
67 //ver2("tim%d %u", i, timers[i].count);
68 }
69 }
70 return timers[0].irq || timers[1].irq || timers[2].irq;
71}
72
73uint32_t tim_read(uint32_t off, int32_t sz)
74{
75 ver2("tim rd %u:%d", off, sz * 8);
76 uint32_t rv;
77 rv = 0;
78 switch(off) {
79 case REG_CRX:
80 break;
81 case REG_CR2:
82 rv |= (timers[0].irq << 0);
83 rv |= (timers[1].irq << 1);
84 rv |= (timers[2].irq << 2);
85 ver2("tim plc %u fc %u rtc %u", timers[0].irq, timers[1].irq, timers[2].irq);
86 //ver2("tim rv %u", rv);
87 break;
88 case REG_T1H:
89 rv = 0;
90 break;
91 case REG_T1L:
92 rv = 31;
93 timers[0].irq = 0;
94 break;
95 case REG_T2H:
96 rv = 12;
97 break;
98 case REG_T2L:
99 rv = 127;
100 timers[1].irq = 0;
101 break;
102 case REG_T3H:
103 rv = 3;
104 break;
105 case REG_T3L:
106 rv = 32;
107 timers[2].irq = 0;
108 break;
109 default:
110 break;
111 }
112 return rv;
113}
114
115void tim_write(uint32_t off, int32_t sz, uint32_t val)
116{
117 ver2("tim wr %u:%d 0x%0*x", off, sz * 8, sz * 2, val);
118 if( off == 0 && (val & (1 << 7)) ) {
119 timers[0].run = true;
120 timers[1].run = true;
121 timers[2].run = true;
122 }
123}
Note: See TracBrowser for help on using the repository browser.