# Assignment 4 – Part 2: Programmable Interval Timer

## Overview
In this part of the assignment, work was done on adding a basic driver for the Programmable Interval Timer (PIT) to the `OSDev_18` kernel. The goal was to initialize the PIT, count timer ticks using IRQ0, and use those ticks to support both busy-wait sleeping and interrupt-based sleeping.

The PIT was configured to use channel 0 and generate regular timer interrupts at `1000 Hz`. This gives a simple timing model where one timer tick is approximately equal to one millisecond.

---

## Implemented Features

### PIT Header and Constants
- Added:
  ```c
  include/kernel/pit.h
  ```
- Defined constants for:
  - PIT command port
  - PIT channel 0 port
  - PIT base frequency
  - target frequency
  - calculated divider
  - ticks-per-millisecond conversion

This provides a single place for PIT-related configuration and function declarations.

---

### PIT Initialization
- Implemented:
  ```c
  void PitInitialize(void);
  ```
- Configures the PIT using:
  ```c
  OutPortByte(PIT_CMD_PORT, 0x36);
  ```
- Loads the PIT divisor into channel 0:
  - low byte first
  - high byte second
- Registers the PIT interrupt handler on:
  ```c
  IRQ0
  ```

This allows the kernel to start receiving regular timer interrupts from the PIT.

---

### Tick Counter
- Added a global tick counter:
  ```c
  static volatile uint32_t pit_ticks = 0;
  ```
- Implemented a helper function:
  ```c
  static uint32_t GetCurrentTick(void);
  ```

The tick counter is incremented every time IRQ0 is triggered. Since the PIT is configured to `1000 Hz`, this gives a simple way to measure elapsed time in milliseconds.

---

### PIT IRQ Handler
- Implemented:
  ```c
  static void PitIrqHandler(struct Registers* regs);
  ```
- The handler:
  - ignores the register argument
  - increments `pit_ticks`

This keeps the timer interrupt path minimal and lets the rest of the kernel measure time by reading the current tick count.

---

### Busy-Wait Sleep
- Implemented:
  ```c
  void SleepBusy(uint32_t milliseconds);
  ```
- Uses the current tick count to wait until enough time has passed
- Continuously checks the tick counter in a loop

This version works by actively spinning on the CPU, so it is simple but inefficient.

---

### Interrupt-Based Sleep
- Implemented:
  ```c
  void SleepInterrupt(uint32_t ticks);
  ```
- Uses:
  ```c
  __asm__ volatile ("sti; hlt");
  ```
  inside a loop
- Re-checks the current tick count after each wake-up

This version is more efficient than busy waiting because the CPU is halted between interrupts instead of constantly polling in a tight loop.

---

### Kernel Integration
- Added:
  ```c
  #include <kernel/pit.h>
  ```
  to `kernel.c`
- Added:
  ```c
  PitInitialize();
  ```
  during kernel startup
- Added:
  ```c
  SleepTest();
  ```
  after the existing memory-allocation test code

This connects the PIT driver to the boot flow so the timer logic is available after interrupt setup is complete.

---

### Build System Update
- Added:
  ```c
  src/pit.c
  ```
  to `CMakeLists.txt`

This ensures the PIT implementation is compiled and linked into the kernel binary together with the rest of the source files.

---

### Terminal Output Fix
- Added the missing declaration for:
  ```c
  void TerminalWriteHex(uint32_t num);
  ```
  to `terminal.h`

This was necessary because `TerminalWriteHex()` was already implemented in `terminal.c` and used in several source files, but it was not exposed through the header.

---

## Testing & Verification

### Build Issues Resolved
During integration, several issues were found and corrected:

- incorrect inline assembly syntax:
  ```c
  __asm__volatile
  ```
  was corrected to:
  ```c
  __asm__ volatile
  ```
- `printf()` calls were removed from PIT test code and replaced with terminal output functions
- the missing `TerminalWriteHex()` declaration in `terminal.h` was added

These changes allowed the kernel to build again with the PIT source included.

---

### Boot Image Verification
- Verified that rebuilding only:
  ```c
  uiaos-kernel
  ```
  updates `kernel.bin`, but does not update the bootable ISO image
- Confirmed that:
  - the new `kernel.bin` contained the new PIT- and memory-related strings
  - the older `kernel.iso` still contained `Hello, World!`
- Rebuilt the image using:
  ```c
  uiaos-create-image
  ```
  so QEMU would boot the updated kernel

This explained why old output was still appearing even after the source code had changed.

---

### Runtime Result
After rebuilding the bootable image, the kernel successfully booted into the updated code and displayed:
- paging setup output
- heap and allocation debug output
- the `memory1`, `memory2`, `memory3`, and `memory4` address prints

This confirms that the updated kernel binary is now being booted correctly.

The PIT sleep test loop was also verified at runtime. The kernel repeatedly prints the expected sleep messages for both:
- busy-wait sleeping
- interrupt-based sleeping

This shows that the PIT tick counter is advancing and that both sleep functions return as expected during execution.

During this test, one remaining issue was observed in the terminal output: once the VGA text buffer wraps back to the top of the screen, new text overwrites old text directly. A cleanup or scrolling improvement for the terminal was noted as a TODO in `kernel.c`.

---

## Conclusion
- Added a PIT driver skeleton to the kernel
- Configured PIT channel 0 for periodic timer interrupts
- Registered an IRQ0 handler and added a global tick counter
- Implemented both busy-wait and interrupt-based sleep functions
- Integrated PIT support into `kernel.c`
- Added `pit.c` to the build system
- Fixed the missing `TerminalWriteHex()` declaration
- Verified that the updated kernel is now booting from the rebuilt ISO image
- Verified that the PIT sleep test loop runs at runtime

This means the code structure for Part 2 is now present in the kernel and has been tested at runtime. The next step is to improve terminal behavior so repeated output does not overwrite earlier lines when the screen wraps.

---

## Next Step
Improve the terminal output behavior so repeated sleep-test messages scroll or clear cleanly instead of overwriting text when the screen wraps back to the top.
