Browse Source

Screen driver

master
Stephen 1 month ago
parent
commit
b747eb4f9e
9 changed files with 215 additions and 25 deletions
  1. +10
    -3
      os/cpu/timer.c
  2. +5
    -0
      os/cpu/timer.h
  3. +134
    -0
      os/drivers/screen.c
  4. +6
    -0
      os/drivers/screen.h
  5. +1
    -1
      os/libc/stdlib.c
  6. +10
    -0
      os/main.c
  7. +30
    -19
      os/prog/tty.c
  8. +16
    -2
      os/start.s
  9. +3
    -0
      os/tests/main.c

+ 10
- 3
os/cpu/timer.c View File

@ -1,5 +1,10 @@
#include "timer.h"
#include "types.h"
// DEBUGGING ONLY
#include "../libc/string.h"
#include "../drivers/serial.h"
#define TIMER_FREQUENCY 385803 // 1000/s
typedef struct
@ -9,7 +14,7 @@ typedef struct
void (*f)();
} Callback;
long long timer_count = 0;
volatile long long timer_count = 0;
Callback callbacks[255];
unsigned char callbackCount = 0;
@ -32,10 +37,12 @@ void timer_interrupt(/* Registers *r */)
}
}
void sleep(long delay) //ms
void sleep(long long delay) //ms
{
long long targetCount = delay * TIMER_FREQUENCY / 1000000 + timer_count;
while(timer_count < targetCount) {}
while(timer_count < targetCount)
{
}
}
// Note this runs within the timer interrupt,


+ 5
- 0
os/cpu/timer.h View File

@ -1,3 +1,8 @@
#ifndef CPU_TIMER_H
#define CPU_TIMER_H
void sleep(long long delay);
int timer_callmelater(void (*f)(), long period);
int timer_stopcallingme(unsigned char position);
#endif

+ 134
- 0
os/drivers/screen.c View File

@ -0,0 +1,134 @@
#include <stdint.h>
#include "serial.h"
// https://www.buydisplay.com/download/democode/ERM24064-1_DemoCode.txt
volatile uint8_t *const SCREEN_ADDRESS_DATA = (uint8_t *)0xf40001;
volatile uint8_t *const SCREEN_ADDRESS_INSTR = (uint8_t *)0xf40003;
// Wait for read and write to not be busy
void lcd_checkBusy_S0S1()
{
uint8_t b;
do
{
b = *SCREEN_ADDRESS_INSTR;
} while((b & 0x03) != 0x03);
}
// Wait for auto write to not be busy
void lcd_checkBusy_S3()
{
uint8_t b;
do
{
b = *SCREEN_ADDRESS_INSTR;
} while((b & 0x08) != 0x08);
}
void lcd_writeData(uint8_t data)
{
*SCREEN_ADDRESS_DATA = data;
}
uint8_t lcd_readData()
{
return *SCREEN_ADDRESS_DATA;
}
void lcd_writeCommand(uint8_t data1, uint8_t data2, uint8_t instruction, int numParameters)
{
if(numParameters >= 1)
{
lcd_checkBusy_S0S1();
lcd_writeData(data1);
}
if(numParameters == 2)
{
lcd_checkBusy_S0S1();
lcd_writeData(data2);
}
// lcd_checkBusy_S3();
*SCREEN_ADDRESS_INSTR = instruction;
}
uint8_t lcd_readByte()
{
lcd_writeCommand(0, 0, 0xc5, 0);
lcd_checkBusy_S0S1();
return lcd_readData();
}
void lcd_setPos(uint8_t x, uint8_t y, uint8_t mode)
{
if(mode)
{
// graphics
int a = y * 40 + x;
uint8_t aLwr = a & 0xff;
uint8_t aUpr = a >> 8;
lcd_writeCommand(aLwr, aUpr + 0x08, 0x24, 2);
}
else
{
// text
int a = y * 40 + x;
uint8_t aLwr = a & 0xff;
uint8_t aUpr = a >> 8;
lcd_writeCommand(aLwr, aUpr, 0x24, 2);
}
}
void lcd_init()
{
lcd_writeCommand(0, 0, 0x40, 2); // Set text home address
lcd_writeCommand(40, 0, 0x41, 2); // Set text area width
lcd_writeCommand(0, 0x08, 0x42, 2); // Set graphics home address
lcd_writeCommand(40, 0, 0x43, 2); // Set graphics area width
lcd_writeCommand(0, 0, 0xa7, 0); // 8-line cursor
lcd_writeCommand(0, 0, 0x80, 0); // OR mode
lcd_writeCommand(0, 0, 0x9c, 0); // text & graphics on
}
void lcd_clear()
{
lcd_setPos(0, 0, 0);
lcd_writeCommand(0, 0, 0xb0, 0);
for(int i = 0; i < 8192; i++)
{
lcd_writeData(0);
}
lcd_writeCommand(0, 0, 0xb2, 0);
}
void lcd_writeString(uint8_t x, uint8_t y, char *str)
{
lcd_setPos(x, y, 0);
while(*str != 0)
{
lcd_writeCommand(*str - 0x20, 0, 0xc0, 1);
str++;
}
}
// Very slow. Use sparingly
void lcd_setpixel(uint8_t x, uint8_t y, uint8_t value)
{
int byteX = x / 6; // 6 bits per character
int bit = 5 - (x - byteX * 6);
lcd_setPos(byteX, y, 1);
uint8_t curValue = lcd_readByte();
if(value)
{
curValue |= 1 << bit;
}
else
{
curValue &= ~(1 << bit);
}
lcd_writeCommand(curValue, 0, 0xc4, 1);
}

+ 6
- 0
os/drivers/screen.h View File

@ -0,0 +1,6 @@
#include <stdint.h>
void lcd_init();
void lcd_clear();
void lcd_writeString(uint8_t x, uint8_t y, char *str);
void lcd_setpixel(uint8_t x, uint8_t y, uint8_t value);

+ 1
- 1
os/libc/stdlib.c View File

@ -47,7 +47,7 @@ unsigned long long strtol(const char *str, char **str_end, unsigned int base)
//base 10 only - temp
unsigned char c = str[i];
if(c >= 'a') c -= 0x20; //lowercase
if(c >= '9') c -= 0x37; //to int
if(c > '9') c -= 0x37; //to int
else c -= '0';
while(c < base && str[i] != 0)
{


+ 10
- 0
os/main.c View File

@ -1,6 +1,8 @@
#include "drivers/serial.h"
#include "drivers/keyboard.h"
#include "drivers/screen.h"
#include "prog/tty.h"
#include "cpu/timer.h"
void kmain()
{
@ -16,6 +18,14 @@ void kmain()
serial_print(0, " \\/ \\/ |_____|_| \\_|_____/|_| |______\\____/ \\/ \\/ |______|_| \\_\\ \\____/|_____/\r\n");
serial_print(0, "===================================================================================================\r\n");
serial_print(0, "www.scd31.com\r\n");
lcd_init();
sleep(1000);
lcd_clear();
sleep(1000);
lcd_writeString(3, 4, "Hello world!");
serial_print(0, "LCD initialized.\r\n");
//keyboard_init();
tty_init();


+ 30
- 19
os/prog/tty.c View File

@ -7,6 +7,7 @@
#include "../libc/string.h"
#include "../libc/stdlib.h"
#include "../drivers/serial.h"
#include "../drivers/screen.h"
#define BUFFER_LEN 1023
@ -59,6 +60,7 @@ void tty_putchar(char c)
serial_putchar(0, c);
}
// TODO why do we disable optimizations? I don't remember
#pragma GCC push_options
#pragma GCC optimize("O0")
void tty_process(char *buf)
@ -87,27 +89,8 @@ void tty_process(char *buf)
tty_print("\r\n");
char buffer[100];
//sprintf(buffer, "Hello! %X\r\n", 0xDEADB33F);
//tty_print(buffer);
//long long a = 0xD;
//long long b = 0x13BEEF;
//sprintf(buffer, "abcdefg: %X %X %X\r\n", a, b, a * b);
//if(a * b == 0)
//{
// tty_print("Yes, it is 0");
//}
//tty_print(buffer);
unsigned char *ptr = (unsigned char *)(unsigned long)strtol(arg, NULL, 0);
if(ptr == 0xB33F)
{
tty_print("It is 0xB33F\r\n");
}
sprintf(buffer, "%X\r\n", (unsigned long long) *ptr);
tty_print(buffer);
@ -129,6 +112,34 @@ void tty_process(char *buf)
char *addr = (char *)(long)strtol(addrStr, NULL, 0);
*addr = (char)valL;
}
else if(strcmp(cmd, "print") == 0)
{
char *xStr = strtok(NULL, " ");
char *yStr = strtok(NULL, " ");
char *text = strtok(NULL, " ");
if(!(xStr && yStr && text))
{
tty_print("Usage: print X Y STRING");
return;
}
int x = strtol(xStr, NULL, 0);
int y = strtol(yStr, NULL, 0);
lcd_writeString(x, y, text);
}
else if(strcmp(cmd, "pixel") == 0)
{
char *xStr = strtok(NULL, " ");
char *yStr = strtok(NULL, " ");
if(!(xStr && yStr))
{
tty_print("Usage: pixel X Y");
return;
}
int x = strtol(xStr, NULL, 0);
int y = strtol(yStr, NULL, 0);
lcd_setpixel(x, y, 1);
}
else
{
tty_print("Unknown command. Type help for help.\r\n");


+ 16
- 2
os/start.s View File

@ -39,17 +39,29 @@
.long 0x17FFFE /* SP at top of 256K of RAM - but it has to be an even address */
.long _start
.long generic_error /* Bus error */
.long generic_error /* Address error */
.long generic_error /* Illegal instruction */
.long generic_error /* Zero divide */
.long generic_error /* CHK instruction */
.long generic_error /* TRAPV instruction */
.long generic_error /* Privilege violation */
.long generic_error /* Trace */
.org 0x100
.long timer_int
.rept 0xBF
.long generic_error
.endr
.org 0x400
_start:
/* Enable interrupts */
/* ANDI.W #0xF8FF, %sr */
ANDI.W #0xF8FF, %sr
/* Disable interrupts */
ORI.W #0x700, %sr
/* ORI.W #0x700, %sr */
JSR kmain
@ -74,3 +86,5 @@ timer_int:
/* return */
RTE
generic_error:
RTE

+ 3
- 0
os/tests/main.c View File

@ -104,6 +104,9 @@ void test_strtol()
{
assert_long(123, strtol("123", 0, 0));
assert_long(0x456, strtol("0x456", 0, 0));
assert_long(0xa, strtol("0xa", 0, 0));
assert_long(0xa, strtol("0xA", 0, 0));
assert_long(9, strtol("9", 0, 0));
}
void test_muldi3()


Loading…
Cancel
Save