Does a lot of work towards the PIT
Added a math library, with clamp and POW. added printf support for printing doubles added a few helper functions in PIT for calcaulting the time in seconds of a clock cycle based on divisor
This commit is contained in:
@ -1,3 +1,64 @@
|
|||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include <kernel/x86/pit.h>
|
#include <kernel/x86/pit.h>
|
||||||
|
#include <kernel/x86/io.h>
|
||||||
|
|
||||||
|
struct pit_state pit;
|
||||||
|
|
||||||
|
uint32_t normalize_divisor(uint32_t divisor)
|
||||||
|
{
|
||||||
|
if (divisor == 0)
|
||||||
|
return 65536;
|
||||||
|
return clamp_u32(divisor, 0, 65535);
|
||||||
|
}
|
||||||
|
|
||||||
|
double get_time_from_divisor(uint32_t divisor)
|
||||||
|
{
|
||||||
|
uint32_t _divisor = normalize_divisor(divisor);
|
||||||
|
|
||||||
|
double clock_rate = 3579545.0 / 3.0; // This is for a bit more precision in the hz rate
|
||||||
|
|
||||||
|
return (_divisor / (clock_rate)) * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Im worried about an overflow
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* What i want to do is
|
||||||
|
*
|
||||||
|
* Every time we get the Timer intterupt, i want to increment a variable, just the amount of times its fired
|
||||||
|
* and then we can use the time rate above to get total time elapsed, which we can use for sleep and stuff
|
||||||
|
*
|
||||||
|
* Im worried about overflows, but i can add something that will automatically flip it over? or do uints already roll over? they already rollover!!! WOOOO!!!
|
||||||
|
* just need to be aware that only a maximum of 52ms * 32int max (64 int max) can be tracked before it rolls over!
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t read_pit_count(uint8_t channel) // Only in lobyte/hibyte mode
|
||||||
|
|
||||||
|
{
|
||||||
|
uint16_t count = 0;
|
||||||
|
|
||||||
|
__asm__ volatile ("cli");
|
||||||
|
|
||||||
|
|
||||||
|
outb(PIT_CMD_REG, (channel << 6)); // xx000000 where x is the channel
|
||||||
|
|
||||||
|
count = inb(channel);
|
||||||
|
count |= inb(channel) << 8;
|
||||||
|
|
||||||
|
return count; // TODO make sure to enable interrupts after this
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_pit_count(uint8_t channel, uint16_t count) // Only in lobyte/hibyte mode
|
||||||
|
{
|
||||||
|
__asm__ volatile ("cli");
|
||||||
|
|
||||||
|
outb(channel, count & 0xFF); // low byte
|
||||||
|
outb(channel, (count & 0xFF00) >> 8); // high byte
|
||||||
|
|
||||||
|
// TODO: make sure to set interrupts
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifndef ARCH_KEYB_H
|
#ifndef ARCH_KEYB_H
|
||||||
#define ARCH_KEYB_H
|
#define ARCH_KEYB_H
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifndef ARCH_PIT_H
|
#ifndef ARCH_PIT_H
|
||||||
#define ARCH_PIT_H
|
#define ARCH_PIT_H
|
||||||
|
|
||||||
@ -16,6 +18,27 @@ enum PIT_CHANNEL {
|
|||||||
CHANNEL_0 = 0x0,
|
CHANNEL_0 = 0x0,
|
||||||
CHANNEL_1,
|
CHANNEL_1,
|
||||||
CHANNEL_2,
|
CHANNEL_2,
|
||||||
|
/**
|
||||||
|
* Isn't supported on 8253 chips, but should be supported on AT and later (except for PS/2).
|
||||||
|
*
|
||||||
|
* Layout goes:
|
||||||
|
* bits:
|
||||||
|
* 76 - Set for READ_BACK
|
||||||
|
* 5 - Latch count flag (0 = latch count, 1 = don't latch count)
|
||||||
|
* 4 - Latch status flag (0 = latch status, 1 = don't latch status) - If this is clear, the next read of the corresponding data port will be a status byte
|
||||||
|
* 3 - Read back timer channel 2 (1 = yes, 0 = no)
|
||||||
|
* 2 - Read back timer channel 1 (..)
|
||||||
|
* 1 - Read back timer channel 0 (..)
|
||||||
|
* 0 - Reserved - set to 0
|
||||||
|
*
|
||||||
|
* Read back status byte:
|
||||||
|
* bits:
|
||||||
|
* 7 - Output pin state
|
||||||
|
* 6 - Null count flags
|
||||||
|
* 54 - Access mode
|
||||||
|
* 321 - Operating mode
|
||||||
|
* 0 BCD/Binary mode
|
||||||
|
*/
|
||||||
READ_BACK // 8254 only
|
READ_BACK // 8254 only
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -28,6 +51,13 @@ enum PIT_CHANNEL {
|
|||||||
* HI AND LOW means that the values will come sequentially through the IO port, lowest followed by highest
|
* HI AND LOW means that the values will come sequentially through the IO port, lowest followed by highest
|
||||||
*/
|
*/
|
||||||
enum PIT_ACCESS_MODE {
|
enum PIT_ACCESS_MODE {
|
||||||
|
/*
|
||||||
|
* To prevent the count from being updated, we can use this command to latch the PIT.
|
||||||
|
* This must be xx000000 ( where x is the channel ).
|
||||||
|
* The value for each channel remains latched, until its fully read (or a new CMD has been issued).
|
||||||
|
* Some older/cheap motherboards have an issue with this command being sent a lot, leading to innaccuracies
|
||||||
|
* this command shouldn't be sent a lot anyways.
|
||||||
|
*/
|
||||||
LATCH_COUNT_VAL_CMD = 0x0,
|
LATCH_COUNT_VAL_CMD = 0x0,
|
||||||
LO_BYTE_ONLY,
|
LO_BYTE_ONLY,
|
||||||
HI_BYTE_ONLY,
|
HI_BYTE_ONLY,
|
||||||
@ -213,5 +243,16 @@ enum PIT_DIGIT_MODE {
|
|||||||
BCD_MODE // four-digit bcd
|
BCD_MODE // four-digit bcd
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pit_state {
|
||||||
|
uint32_t divisor;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
void init_pit(uint32_t divisor);
|
||||||
|
|
||||||
|
double get_time_from_divisor(uint32_t divisor);
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t read_pit_count(uint8_t channel);
|
||||||
|
void set_pit_count(uint8_t channel, uint16_t count);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <kernel/x86/io.h>
|
#include <kernel/x86/io.h>
|
||||||
#include <kernel/x86/keyb.h>
|
#include <kernel/x86/keyb.h>
|
||||||
|
|
||||||
|
#include <kernel/x86/pit.h>
|
||||||
|
|
||||||
|
|
||||||
void kmain(void)
|
void kmain(void)
|
||||||
@ -27,6 +28,8 @@ void kmain(void)
|
|||||||
|
|
||||||
init_kb();
|
init_kb();
|
||||||
|
|
||||||
|
printf("%f\n", get_time_from_divisor(10));
|
||||||
|
|
||||||
printf("Entering loop...\n");
|
printf("Entering loop...\n");
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
|
13
libc/include/math.h
Normal file
13
libc/include/math.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifndef MATH_H
|
||||||
|
#define MATH_H
|
||||||
|
|
||||||
|
int pow(int base, int exp);
|
||||||
|
|
||||||
|
uint8_t clamp_u8(uint8_t val, uint8_t min, uint8_t max);
|
||||||
|
uint16_t clamp_u16(uint16_t val, uint16_t min, uint16_t max);
|
||||||
|
uint32_t clamp_u32(uint32_t val, uint32_t min, uint32_t max);
|
||||||
|
uint64_t clamp_u64(uint64_t val, uint64_t min, uint64_t max);
|
||||||
|
|
||||||
|
#endif
|
@ -20,5 +20,7 @@ char* u8toa(uint8_t num, char* buf, int base);
|
|||||||
char* itoa(int num, char* buf, int base);
|
char* itoa(int num, char* buf, int base);
|
||||||
char* utoa(unsigned int num, char* buf, int base);
|
char* utoa(unsigned int num, char* buf, int base);
|
||||||
|
|
||||||
|
char* dtoa(double n, char* buf, int afterpoint);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
39
libc/math/clamp.c
Normal file
39
libc/math/clamp.c
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
uint8_t clamp_u8(uint8_t val, uint8_t min, uint8_t max)
|
||||||
|
{
|
||||||
|
if (val > max)
|
||||||
|
return max;
|
||||||
|
if (val < min)
|
||||||
|
return min;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t clamp_u16(uint16_t val, uint16_t min, uint16_t max)
|
||||||
|
{
|
||||||
|
if (val > max)
|
||||||
|
return max;
|
||||||
|
if (val < min)
|
||||||
|
return min;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t clamp_u32(uint32_t val, uint32_t min, uint32_t max)
|
||||||
|
{
|
||||||
|
if (val > max)
|
||||||
|
return max;
|
||||||
|
if (val < min)
|
||||||
|
return min;
|
||||||
|
return val;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t clamp_u64(uint64_t val, uint64_t min, uint64_t max)
|
||||||
|
{
|
||||||
|
if (val > max)
|
||||||
|
return max;
|
||||||
|
if (val < min)
|
||||||
|
return min;
|
||||||
|
return val;
|
||||||
|
}
|
9
libc/math/pow.c
Normal file
9
libc/math/pow.c
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
int pow(int base, int exp)
|
||||||
|
{
|
||||||
|
int res = base;
|
||||||
|
for (int i = 0; i < exp; i++)
|
||||||
|
res *= base;
|
||||||
|
return res;
|
||||||
|
}
|
@ -77,6 +77,18 @@ int printf(const char* restrict format, ...) {
|
|||||||
if (!print(buffer, len))
|
if (!print(buffer, len))
|
||||||
return -1;
|
return -1;
|
||||||
written += len;
|
written += len;
|
||||||
|
} else if (*format == 'f') {
|
||||||
|
format++;
|
||||||
|
double d = (double) va_arg(parameters, double);
|
||||||
|
dtoa(d, buffer, 5);
|
||||||
|
size_t len = strlen(buffer);
|
||||||
|
if (maxrem < len) {
|
||||||
|
// TODO
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!print(buffer, len))
|
||||||
|
return -1;
|
||||||
|
written += len;
|
||||||
} else if (*format == 'u') {
|
} else if (*format == 'u') {
|
||||||
format++;
|
format++;
|
||||||
unsigned int i = (unsigned int) va_arg(parameters, unsigned int);
|
unsigned int i = (unsigned int) va_arg(parameters, unsigned int);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
static void reverse(char* buf, int len)
|
static void reverse(char* buf, int len)
|
||||||
{
|
{
|
||||||
@ -273,3 +275,35 @@ char* utoa(unsigned int num, char* buf, int base)
|
|||||||
reverse(buf, i); // reverse, since we did it backwards!
|
reverse(buf, i); // reverse, since we did it backwards!
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dbl_to_str(int x, char* buf, int d)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (x) {
|
||||||
|
buf[i++] = (x % 10) + '0';
|
||||||
|
x = x / 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i < d)
|
||||||
|
buf[i++] = '0';
|
||||||
|
|
||||||
|
reverse(buf, i);
|
||||||
|
buf[i] = '\0';
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* dtoa(double n, char* buf, int afterpoint)
|
||||||
|
{
|
||||||
|
int whole = (int) n;
|
||||||
|
|
||||||
|
double decimals = n - (double) whole;
|
||||||
|
|
||||||
|
int i = dbl_to_str(whole, buf, 0);
|
||||||
|
if (afterpoint != 0) {
|
||||||
|
buf[i] = '.'; // add the decimal
|
||||||
|
|
||||||
|
decimals = decimals * pow(10, afterpoint);
|
||||||
|
dbl_to_str((int) decimals, buf + i + 1, afterpoint + 1);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user