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