merge
[dcpu16] / hw_clock.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <errno.h>
4
5 #include "dcpu16.h"
6 #include "hw_clock.h"
7
8 #define MSG_(__level__, __vm__, ...) do { ((__vm__) ? ((struct dcpu16 *)(__vm__))->msg_cb_ : dcpu16_msg_)(__level__, __VA_ARGS__); } while (0)
9 #define MSG_INFO(__vm__, ...) MSG_(DCPU16_MSG_INFO, __vm__, __VA_ARGS__)
10 #define MSG_ERROR(__vm__, ...) MSG_(DCPU16_MSG_ERROR, __vm__, __VA_ARGS__)
11 #ifdef DEBUG
12 #define MSG_DEBUG(__vm__, ...) MSG_(DCPU16_MSG_DEBUG, __vm__, __VA_ARGS__)
13 #else /* DEBUG */
14 #define MSG_DEBUG(__vm__, ...) do { } while (0)
15 #endif /* DEBUG */
16
17 struct clock_ {
18 DCPU16_WORD cycle_;
19 DCPU16_WORD rate;
20 DCPU16_WORD tick;
21 DCPU16_WORD interrupt_message;
22 };
23
24 static
25 void clock_reset_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
26 struct clock_ *clock = (struct clock_ *)hw->data;
27
28 (void)vm;
29
30 memset(clock, 0, sizeof *clock);
31 }
32
33 static
34 void clock_cycle_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
35 struct clock_ *clock = (struct clock_ *)hw->data;
36
37 /* cycle is only called 100000 times per second */
38 /* maximum rate is 60hz / word_max = 3932160 */
39
40 if (clock->rate == 0)
41 return;
42
43 clock->cycle_++;
44 if (clock->cycle_ >= clock->rate) {
45 /* THIS CHECK IS WRONG, JUST A PLACEHOLDER */
46 clock->cycle_ = 0;
47 clock->tick += 1;
48
49 if (clock->interrupt_message) {
50 if (dcpu16_interrupt(vm, clock->interrupt_message))
51 MSG_ERROR(vm, "%s: could not send interrupt", hw->mod->name_);
52 }
53 }
54 }
55
56 static
57 void clock_hwi_(struct dcpu16 *vm, struct dcpu16_hw *hw) {
58 struct clock_ *clock = (struct clock_ *)hw->data;
59 DCPU16_WORD reg_a = vm->reg[DCPU16_REG_A];
60 DCPU16_WORD reg_b = vm->reg[DCPU16_REG_B];
61
62 switch (reg_a) {
63 case 0: /* set tick gather rate, 60hz/B */
64 clock->rate = reg_b;
65 break;
66
67 case 1: /* fetch elapsed count since rate was set */
68 vm->reg[DCPU16_REG_C] = clock->tick;
69 break;
70
71 case 2:
72 clock->interrupt_message = reg_b;
73 break;
74 }
75 }
76
77 static
78 int clock_data_init_(struct dcpu16_hw *hw, void *data) {
79 (void)data;
80
81 hw->data = calloc(1, sizeof(struct clock_));
82 if (hw->data == NULL) {
83 MSG_ERROR(hw->vm, "%s():%s", "calloc", strerror(errno));
84 return -1;
85 }
86 return 0;
87 }
88
89 static
90 void clock_data_free_(struct dcpu16_hw *hw) {
91 if (hw) {
92 if (hw->data) {
93 free(hw->data);
94 hw->data = NULL;
95 }
96 }
97 }
98
99
100 struct dcpu16_hw_module dcpu16_hw_module_clock = {
101 .name_ = "Generic Clock (compatible)",
102
103 .id_l = 0xb402,
104 .id_h = 0x12d0,
105 .ver = 0x0001,
106 .mfg_l = 0x0000,
107 .mfg_h = 0x0000,
108 .hwi = clock_hwi_,
109 .cycle = clock_cycle_,
110 .reset = clock_reset_,
111
112 .data_init = clock_data_init_,
113 .data_free = clock_data_free_,
114 .ctl = NULL,
115 .ctl_cmd = NULL,
116 };