Project

General

Profile

Statistics
| Revision:

root / lab2 / src / timer.c @ 252

History | View | Annotate | Download (4.11 KB)

1 196 up20180642
#include <lcom/lcf.h>
2
3
#include "timer.h"
4
5
#include "i8254.h"
6
#include "utils.h"
7
#include "errors.h"
8
9
//7.1 timer_test_read_config()
10
int (timer_get_conf)(uint8_t timer, uint8_t *st) {
11
    if(st == NULL) return 1;
12
    // Write read-back command to TIMER_CTRL
13
    u32_t cmd = TIMER_RB_CMD | TIMER_RB_COUNT_ | TIMER_RB_SEL(timer);
14
    if(sys_outb(TIMER_CTRL, cmd)) return 1;
15
    int read_port;
16
    switch(timer) {
17
        case 0: read_port = TIMER_0; break;
18
        case 1: read_port = TIMER_1; break;
19
        case 2: read_port = TIMER_2; break;
20
        default: return 1;
21
    }
22
    if(util_sys_inb(read_port, st)) return 1;
23
    return 0;
24
}
25
int (timer_display_conf)(uint8_t timer, uint8_t st, enum timer_status_field field) {
26
    union timer_status_field_val conf;
27
    uint8_t in_mode;
28
    switch(field){
29
        case tsf_all:
30
            conf.byte = st; /* Full Status Byte */
31
            break;
32
        case tsf_initial:
33
            /* Counter Initial Value Loading Mode */
34
            in_mode = (st & TIMER_INMODE_MASK) >> TIMER_INMODE_POS;
35
            switch(in_mode){
36
                case 0: conf.in_mode = INVAL_val    ; break; //000
37
                case 1: conf.in_mode = LSB_only     ; break; //001
38
                case 2: conf.in_mode = MSB_only     ; break; //010
39
                case 3: conf.in_mode = MSB_after_LSB; break; //011
40
                default: return 1;
41
            }
42
            break;
43
        case tsf_mode:
44
            /* Counting Mode */
45
            conf.count_mode = (st & TIMER_MODE_MASK)>>TIMER_MODE_POS;
46
            if(conf.count_mode == TIMER_MODE_2ALT || conf.count_mode == TIMER_MODE_3ALT)
47
                conf.count_mode &= TIMER_MODE_RED2;
48
            break;
49
        case tsf_base:
50
            /* Representation of Counter Initial Value */
51
            conf.bcd = st & TIMER_BCD;
52
            break;
53
        default: return 1;
54
    }
55
    if(timer_print_config(timer, field, conf)) return 1;
56
    return 0;
57
}
58
//7.2 timer_test_time_base()
59
int (timer_set_frequency)(uint8_t timer, uint32_t freq) {
60
61
    // Frequencies out this range are not supported (by limitation of hardware)
62
    if (freq > TIMER_FREQ || freq < TIMER_MIN_FREQ) {
63
        printf("%s: Frequency out of range, must be between %d and %d.\n", __func__, TIMER_MIN_FREQ, TIMER_FREQ);
64
        return 1;
65
    }
66
67
    uint8_t status = 0;
68
    if (timer_get_conf(timer, &status)) return 1;
69
    //Make command
70
    uint8_t write_cmd = 0;
71
    //Select timer
72
    switch(timer) {
73
        case 0: write_cmd |= TIMER_SEL0; break;
74
        case 1: write_cmd |= TIMER_SEL1; break;
75
        case 2: write_cmd |= TIMER_SEL2; break;
76
        default: return 1;
77
    }
78
    //Change both LSB and MSB
79
    write_cmd |= TIMER_LSB_MSB;
80
    //Keep 4 least significant bits
81
    write_cmd |= (status & (TIMER_MODE_MASK | TIMER_BCD));
82
    //Write cmd
83
    if (sys_outb(TIMER_CTRL, write_cmd)) return 1;
84
85
    // counter_init = clock/freq
86
    uint16_t counter_init = (uint16_t)(TIMER_FREQ / freq);
87
88
    int timer_port = 0;
89
    switch(timer) {
90
        case 0: timer_port = TIMER_0; break;
91
        case 1: timer_port = TIMER_1; break;
92
        case 2: timer_port = TIMER_2; break;
93
        default: return 1;
94
    }
95
    uint8_t lsb = 0, msb = 0;
96
    /* Split the 16 bits word in two bytes */
97
    if (util_get_LSB(counter_init, &lsb)) return 1;
98
    if (util_get_MSB(counter_init, &msb)) return 1;
99
100
    /* Write the 8 LSB of the counter */
101
    if (sys_outb(timer_port, lsb)) return 1;
102
    /* Write the 8 MSB of the counter */
103
    if (sys_outb(timer_port, msb)) return 1;
104
105
    return 0;
106
}
107
//7.3 timer_test_int()
108
void (timer_int_handler)(void) {
109
    no_interrupts++;
110
}
111
#ifdef LAB2
112
    static int hook_id;
113
    int (timer_subscribe_int)(uint8_t *bit_no) {
114
        if(bit_no == NULL) return NULL_PTR;
115
        hook_id = 2;
116
        *bit_no = hook_id;
117
        return sys_irqsetpolicy(TIMER0_IRQ, IRQ_REENABLE, &hook_id);
118
    }
119
    int (timer_unsubscribe_int)() {
120
        return unsubscribe_interrupt(&hook_id);
121
    }
122
#endif
123
int (subscribe_timer_interrupt)(uint8_t interrupt_bit, int *interrupt_id) {
124
    if (interrupt_id == NULL) return 1;
125
    *interrupt_id = interrupt_bit;
126
    return (sys_irqsetpolicy(TIMER0_IRQ, IRQ_REENABLE, interrupt_id));
127
}
128
uint32_t no_interrupts = 0;