Compare commits

...

13 Commits

27 changed files with 672 additions and 275 deletions

4
.gitignore vendored
View File

@ -1,2 +1,2 @@
omega.g3a
.vscode/
omega.g3a
.vscode/

View File

@ -1,5 +1,5 @@
CC=sh-elf-gcc
CFLAGS= -Iinclude -ffreestanding -flto -nostdlib -O2 -Wall -Wextra
CFLAGS= -Iinclude -ffreestanding -flto -nostdlib -O2 -Wall -Wextra -Xlinker
NAME=
FILENAME="omega"
OBJCOPY = sh-elf-objcopy
@ -8,8 +8,8 @@ CONV_DIR=oconv
BUILD_DIR=build
SRC := $(wildcard $(SRC_DIR)/*.c $(SRC_DIR)/*.S)
SRC += $(wildcard $(SRC_DIR)/*/*.c $(SRC_DIR)/*/*.S)
SRC := $(wildcard $(SRC_DIR)/*.c $(SRC_DIR)/*.s)
SRC += $(wildcard $(SRC_DIR)/*/*.c $(SRC_DIR)/*/*.s)
all: mkdir convert compile clean
no_clean : mkdir convert compile

View File

@ -1,6 +1,6 @@
# omega
omega is a micro kernel for Casio FX-CG 50 (Graph 90+E in France). omega is in developpement and it will be very simple, but i will try to provides basic functions.
omega is a micro kernel for Casio FX-CG 50 (Graph 90+E in France).
## build
@ -11,9 +11,9 @@ you can build sample program (provided in main.c) with
## project progress
You can do principal things with display, i.e :
- set and reset pixels on VRAM
- display .png images converted with oconv
- print string and int
Here are the features supported :
- Display driver and display functions - interact with VRAM, display image with omega's converter oconv, print text in printf-like format...
- Basic keyboard functions - only keydown() for the moment
- An interrupt/exception/TLB handler, in order to provide a complete "OS-proof" kernel

View File

@ -1,2 +1,2 @@
rick.png : image, rick
rick.png : image, rick
font.png : image, font

View File

@ -1,3 +1,4 @@
#include <stddef.h>
void coreinit(void);
#include <stddef.h>
#include <stdint.h>
void coreinit(void);
uint32_t ramaddr(void);

6
include/omega/cpu.h Normal file
View File

@ -0,0 +1,6 @@
#include <stdint.h>
void cpu_set_vbr(uint32_t VBR);
uint32_t cpu_get_vbr(void);
void cpu_init(void);
void cpu_exit();

View File

@ -0,0 +1,4 @@
#define ONORETURN __attribute__((noreturn))
#define OIHANDLER __attribute__((interrupt_handler))
#define OINTH __attribute__((section(".omega.inth")))
#define OENTRY __attribute__((section(".text.entry")))

View File

@ -1,7 +1,10 @@
#include <stdint.h>
#define rgb565(r, g, b) (((r & 0x1F) << 11) | ((g & 0x3F) << 5) | (b & 0x1F))
#define C_BLACK rgb565(0,0,0)
#define C_RED rgb565(255,0,0)
#define C_WHITE rgb565(255,255,255)
#define DWIDTH 396
#define DHEIGHT 224
// image_t type for images
typedef struct
@ -12,7 +15,7 @@ typedef struct
uint16_t pixels[];
} image_t;
extern uint16_t vram[396*224];
extern uint16_t vram[DWIDTH*DHEIGHT];
// put pixel in VRAM at position (x,y) with color
void dpixel(int x,int y,uint16_t color);
// display vram
@ -21,5 +24,6 @@ void dupdate(void);
void dinit(void);
void dimage(int x, int y, image_t *image);
void dclear(void);
void dtext(int x, int y, char *str);
void dprintf(int x, int y, char *format, ...);
void dtext(int x, int y, char *str, uint16_t color);
void dprintf(int x, int y, uint16_t color, char *format, ...);
void drect(int x1, int y1, int x2, int y2, uint16_t color);

75
include/omega/keyboard.h Normal file
View File

@ -0,0 +1,75 @@
#include <omega/utils.h>
#include <stdbool.h>
extern uint8_t scan[12];
void keyboard_refresh();
void keyboard_setup();
uint8_t keyboard_get_line(int line);
bool keydown(int key);
// Keycodes
enum {
KEY_F1 = 0x91,
KEY_F2 = 0x92,
KEY_F3 = 0x93,
KEY_F4 = 0x94,
KEY_F5 = 0x95,
KEY_F6 = 0x96,
KEY_SHIFT = 0x81,
KEY_OPTN = 0x82,
KEY_VARS = 0x83,
KEY_MENU = 0x84,
KEY_LEFT = 0x85,
KEY_UP = 0x86,
KEY_ALPHA = 0x71,
KEY_SQUARE = 0x72,
KEY_POWER = 0x73,
KEY_EXIT = 0x74,
KEY_DOWN = 0x75,
KEY_RIGHT = 0x76,
KEY_XOT = 0x61,
KEY_LOG = 0x62,
KEY_LN = 0x63,
KEY_SIN = 0x64,
KEY_COS = 0x65,
KEY_TAN = 0x66,
KEY_FRAC = 0x51,
KEY_FD = 0x52,
KEY_LEFTP = 0x53,
KEY_RIGHTP = 0x54,
KEY_COMMA = 0x55,
KEY_ARROW = 0x56,
KEY_7 = 0x41,
KEY_8 = 0x42,
KEY_9 = 0x43,
KEY_DEL = 0x44,
KEY_4 = 0x31,
KEY_5 = 0x32,
KEY_6 = 0x33,
KEY_MUL = 0x34,
KEY_DIV = 0x35,
KEY_1 = 0x21,
KEY_2 = 0x22,
KEY_3 = 0x23,
KEY_ADD = 0x24,
KEY_SUB = 0x25,
KEY_0 = 0x11,
KEY_DOT = 0x12,
KEY_EXP = 0x13,
KEY_NEG = 0x14,
KEY_EXE = 0x15,
KEY_ACON = 0x07,
};

View File

@ -1,10 +1,12 @@
#include <stdarg.h>
#include <stddef.h>
void reverse(char str[], int length);
char* itoa(int num, char* str, int base);
int vsnprintf(char* str, size_t size, const char* format, va_list arg);
char * strcpy(char *strDest, const char *strSrc);
char * strcat(char *dest, const char *src);
size_t strlen(const char *str);
int vsprintf(char *buffer, char *format, va_list args);
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
void reverse(char str[], int length);
char* itoa(uint32_t num, char* str, int base);
int vsnprintf(char* str, size_t size, const char* format, va_list arg);
char * strcpy(char *strDest, const char *strSrc);
char * strcat(char *dest, const char *src);
size_t strlen(const char *str);
int vsprintf(char *buffer, char *format, va_list args);
void memcpy(uint32_t * l, uint32_t *r, int32_t s);

View File

@ -1,41 +1,67 @@
ENTRY(_start)
MEMORY
{
rom (rx): o = 0x00300000, l = 2M
/*First 0x1400 bytes are reserved for VBR (starting at 0x08100000)*/
ram (rw): o = 0x08101400, l = 491k
}
SECTIONS
{
_srom = SIZEOF(.pretext) + SIZEOF(.text) + SIZEOF(.rodata);
.pretext : {
*(.text.entry)
} > rom
.text : {
_exch_start = . ;
*(.omega.exch)
_exch_size = ABSOLUTE (. - _exch_start);
_inth_start = . ;
*(.omega.inth)
_inth_size = ABSOLUTE (. - _inth_start);
. = ALIGN(4);
_tlbh_start = . ;
*(.omega.tlbh)
_tlbh_size = ABSOLUTE (. - _tlbh_start);
*(.text .text.*)
} > rom
.rodata : {
*(.rodata .rodata.*)
} > rom
. = ORIGIN(ram);
.data : {
_rdata = .;
*(.data .data.*)
*(.omega.vram)
_ldata = LOADADDR(.data);
} > ram AT > rom
_sdata = SIZEOF(.data);
.bss (NOLOAD) : {
_rbss = . ;
*(.bss .bss.* COMMON)
} > ram
} > ram :NONE
_sbss = SIZEOF(.bss);
_sbss = SIZEOF(.bss);
.rodata : {
*(.rodata .rodata.*)
} > rom
/* not important : comments */

View File

@ -1,72 +1,72 @@
import subprocess
import sys
import os
from PIL import Image
def rgb_to_rgb565(rgb_tuple):
r = rgb_tuple[0]
g = rgb_tuple[1]
b = rgb_tuple[2]
return (int(r/255*31)<<11)|(int(g/255*63)<<5) | int(b/255*31)
class image:
def __init__(self, path):
self.image = Image.open(path)
def getImage(self):
return self.image
def setImage(self,path):
self.image = Image.open(path)
def getpixels(self):
width, height = self.image.size
pixels = []
for y in range(height):
for x in range(width):
pixel = self.image.getpixel((x, y))
pixels.append(rgb_to_rgb565(pixel))
return pixels
class converter:
def __init__(self, file):
self.file = file
def getFile(self):
return self.file
def setFile(self, file):
self.file = file
def write_word(self, data):
asm = ""
asm += ".word " + hex(data)
return asm
def convert_image(self, symbol, section=".rodata"):
img = image(self.file)
asmc = f".section {section} \n"
asmc += f".global _{symbol}\n"
asmc += f"_{symbol}:\n"
width,height = img.getImage().size
asmc += self.write_word(height) + "\n"
asmc += self.write_word(width) + "\n"
pixels = img.getpixels()
for i in pixels:
asmc += self.write_word(i) + "\n"
f = open(symbol + ".S", "wb")
f.write(asmc.encode('utf-8'))
f.close()
dir = sys.argv[1]
ls = os.listdir(dir)
if not "oconv.txt" in ls:
print(" OConv ----- oconv.txt cannot be found")
exit()
print("\n")
conf = open(f"{dir}oconv.txt", 'r').read().replace(" ","")
files = conf.split("\n")
for file in files:
filename, metadatas = file.split(":")
type, name = metadatas.split(",")
print(f" OConv ----- Converting {filename}")
conv = converter(dir+filename)
if(type == "image"):
conv.convert_image(name)
print("\n")
import subprocess
import sys
import os
from PIL import Image
def rgb_to_rgb565(rgb_tuple):
r = rgb_tuple[0]
g = rgb_tuple[1]
b = rgb_tuple[2]
return (int(r/255*31)<<11)|(int(g/255*63)<<5) | int(b/255*31)
class image:
def __init__(self, path):
self.image = Image.open(path)
def getImage(self):
return self.image
def setImage(self,path):
self.image = Image.open(path)
def getpixels(self):
width, height = self.image.size
pixels = []
for y in range(height):
for x in range(width):
pixel = self.image.getpixel((x, y))
pixels.append(rgb_to_rgb565(pixel))
return pixels
class converter:
def __init__(self, file):
self.file = file
def getFile(self):
return self.file
def setFile(self, file):
self.file = file
def write_word(self, data):
asm = ""
asm += ".word " + hex(data)
return asm
def convert_image(self, symbol, section=".rodata"):
img = image(self.file)
asmc = f".section {section} \n"
asmc += f".global _{symbol}\n"
asmc += f"_{symbol}:\n"
width,height = img.getImage().size
asmc += self.write_word(height) + "\n"
asmc += self.write_word(width) + "\n"
pixels = img.getpixels()
for i in pixels:
asmc += self.write_word(i) + "\n"
f = open(symbol + ".S", "wb")
f.write(asmc.encode('utf-8'))
f.close()
dir = sys.argv[1]
ls = os.listdir(dir)
if not "oconv.txt" in ls:
print(" OConv ----- oconv.txt cannot be found")
exit()
print("\n")
conf = open(f"{dir}oconv.txt", 'r').read().replace(" ","")
files = conf.split("\n")
for file in files:
filename, metadatas = file.split(":")
type, name = metadatas.split(",")
print(f" OConv ----- Converting {filename}")
conv = converter(dir+filename)
if(type == "image"):
conv.convert_image(name)
print("\n")

View File

@ -1,27 +1,20 @@
//---
// core.c - Initialize core of Omega kernel
// core.c - Core of Omega kernel
//---
#include <omega/core.h>
#include <stdint.h>
#include <stddef.h>
#include <omega/utils.h>
#include <omega/display.h>
/* Symbols that came from linker script */
extern uint32_t
ldata, sdata, rdata, /* .data section informations */
sbss, rbss; /* .bss section informations */
sbss, rbss; /* .bss section informations */
/* Copy data of size s from one address l to another address r*/
void copy(uint32_t * l, int32_t s, uint32_t *r)
{
while(s > 0)
{
*r++ = *l++;
s -= 4;
}
}
/* Clean a section of size s beginning at adress a*/
void clean(uint32_t * a, int32_t s)
@ -36,12 +29,14 @@ void clean(uint32_t * a, int32_t s)
/* Copy .data section from ROM to RAM - needed at start of kernel */
void rcopy(void)
{
copy(&ldata,(int32_t)&sdata,&rdata);
memcpy(&ldata,&rdata,(int32_t) sdata);
}
/* Clean .bss section of the RAM */
void rclean(void)
{
clean(&rbss,(int32_t)&sbss);
}
/* Initialize kernel*/
void coreinit(void)

View File

@ -4,20 +4,31 @@
#include <omega/core.h>
#include <omega/display.h>
#include <omega/cpu.h>
#include <omega/keyboard.h>
#include <omega/defs/attributes.h>
int main();
extern uint32_t rbss;
// This function loads omega. It initialize drivers, do some stuff with memory...
__attribute__((section(".text.entry")))
void start()
{
// Copy ROM to RAM for static and global variables and cleans .bss
OENTRY int start()
{
// Copy ROM to RAM for static and global variables and clean .bss
coreinit();
// Init CPU (setup registers)
cpu_init();
// Setup keyboard
keyboard_setup();
//call user's main() function
main();
cpu_exit();
return 1;
}

117
src/cpu/cpu.c Normal file
View File

@ -0,0 +1,117 @@
//---
// cpu.c - CPU functions definitions for omega kernel
//---
#include <omega/cpu.h>
#include <omega/core.h>
#include <omega/display.h>
#include <omega/utils.h>
#include <omega/defs/attributes.h>
#include "tlbh.h"
#include "exch.h"
#include "inth.h"
extern uint32_t _bram;
extern uint32_t exch_size, inth_size, tlbh_size;
static uint32_t VBR = 0x8c200000;
ONORETURN void cpu_panic(void)
{
// Read the EXPEVT register
uint32_t code = *(uint32_t *)0xff000024;
char const *name = "";
if(code == 0x040) name = "TLB miss (read)";
if(code == 0x060) name = "TLB miss (write)";
if(code == 0x0e0) name = "Data address error (read)";
if(code == 0x100) name = "Data address error (write)";
if(code == 0x160) name = "Unconditional trap (TRAPA)";
if(code == 0x180) name = "Illegal instruction";
if(code == 0x1a0) name = "Illegal delay slot";
uint32_t PC;
__asm__("stc spc, %0" : "=r"(PC));
uint32_t TEA = *(volatile uint32_t *)0xff00000c;
uint32_t TRA = *(volatile uint32_t *)0xff000020 >> 2;
while(1)
{
dclear();
drect(0,0,DWIDTH,10,C_RED);
dprintf(1,1,C_WHITE, "An exception occured !");
dprintf(1,20,C_BLACK, "%x : %s", code, name);
dprintf(1,50,C_BLACK, "PC = %x",PC);
dprintf(200,50,C_BLACK,"(Error address)");
dprintf(1,70,C_BLACK, "TEA = %x",TEA);
dprintf(200,70,C_BLACK,"(Problematic address)");
dprintf(1,90,C_BLACK, "TRA = %x",TRA);
dprintf(200,90,C_BLACK,"(Trap number)");
dprintf(1,140,C_BLACK, "Please reset your calculator.");
dupdate();
}
}
uint8_t IMRSAV[13];
uint8_t volatile *IMR = (void *)0xA4080080;
uint8_t volatile *IMCR = (void *)0xa40800c0;
void cpu_imr_save(void)
{
uint8_t volatile *CURIMR = IMR;
for(int i=0;i<13;i++,CURIMR+=4)
{
IMRSAV[i] = *CURIMR;
}
}
void cpu_imr_restore(void)
{
uint8_t volatile *CURIMR = IMR;
uint8_t volatile *CURIMCR = IMCR;
for(int i=0;i<13;i++,CURIMR+=4,CURIMCR+=4)
{
*CURIMCR = 0xff;
*CURIMR = IMRSAV[i];
}
}
uint32_t VBRSAV;
void cpu_vbr_save()
{
VBRSAV = cpu_get_vbr();
}
void cpu_vbr_restore()
{
cpu_set_vbr(VBRSAV);
}
void cpu_init(void)
{
// Save IMR
cpu_imr_save();
cpu_vbr_save();
// Disable interrupts that we don't handle
uint8_t volatile *CURIMR = IMR;
for(int i=0;i<13;i++,CURIMR+=4)
{
*CURIMR = 0xff;
}
// We copy our handlers...
memcpy((uint32_t *)&cpu_exch,(uint32_t *)(VBR+0x100),(int32_t)&exch_size);
memcpy((uint32_t *)&cpu_tlbh,(uint32_t *)(VBR+0x400),(int32_t)&tlbh_size);
memcpy((uint32_t *)&cpu_inth,(uint32_t *)(VBR+0x600),(int32_t)&inth_size);
// ... and then we can change the VBR
cpu_set_vbr(VBR);
}
void cpu_exit()
{
cpu_vbr_restore();
cpu_imr_restore();
}

1
src/cpu/exch.h Normal file
View File

@ -0,0 +1 @@
void cpu_exch(void);

16
src/cpu/exch.s Normal file
View File

@ -0,0 +1,16 @@
.global _cpu_exch
.section .omega.exch, "ax"
.balign 4
_cpu_exch:
stc ssr, r0
ldc r0, sr
mov.l .panic, r0
jmp @r0
nop
.balign 4
.panic:
.long _cpu_panic

1
src/cpu/inth.h Normal file
View File

@ -0,0 +1 @@
void cpu_inth(void);

7
src/cpu/inth.s Normal file
View File

@ -0,0 +1,7 @@
.global _cpu_inth
.section .omega.inth, "ax"
.balign 4
_cpu_inth:
rte

15
src/cpu/registers.s Normal file
View File

@ -0,0 +1,15 @@
# registers.s - Registers definition
.global _cpu_set_vbr
.global _cpu_get_vbr
.text
_cpu_set_vbr:
ldc r4,vbr
rts
nop
_cpu_get_vbr:
stc vbr, r0
rts
nop

1
src/cpu/tlbh.h Normal file
View File

@ -0,0 +1 @@
void cpu_tlbh(void);

61
src/cpu/tlbh.s Normal file
View File

@ -0,0 +1,61 @@
.global _cpu_tlbh
.section .omega.tlbh, "ax"
.balign 4
_cpu_tlbh:
/* Save registers*/
sts.l pr, @-r15
stc.l gbr, @-r15
sts.l mach, @-r15
sts.l macl, @-r15
/* Is it possible to map TEA to TLB ? If not, well - panic*/
mov.l .tea, r0
mov.l @r0, r0
mov.l .max_mapped_rom, r1
cmp/ge r1, r0
bt panic
mov.l .min_mapped_rom, r1
cmp/ge r1, r0
bf panic
/* Okay it's possible to map so here we go */
mov #12, r0
mov.l .syscall, r2
jsr @r2
nop
lds.l @r15+, macl
lds.l @r15+, mach
ldc.l @r15+, gbr
lds.l @r15+, pr
rte
nop
/* Call VBR exception panic*/
panic:
lds.l @r15+, macl
lds.l @r15+, mach
ldc.l @r15+, gbr
lds.l @r15+, pr
stc vbr, r0
mov #1, r1
shll8 r1
add r1, r0
jmp @r0
nop
.align 4
.tea:
.long 0xff00000c
.min_mapped_rom:
.long 0x00300000
.max_mapped_rom:
.long 0x00300000 + _srom
.syscall:
.long 0x80020070

View File

@ -14,20 +14,32 @@ float floor(float x) {
return (float)((int)x);
}
uint16_t vram[396*224];
extern image_t font;
void dupdate(void)
{
rdisplay(vram);
}
void dpixel(int x,int y,uint16_t color)
{
vram[y * 397 + x] = color;
if((x>=0 && x<DWIDTH) && (y>=0 && y<DHEIGHT)) vram[y * DWIDTH + x] = color;
}
void drect(int x1, int y1, int x2, int y2, uint16_t color)
{
for(int x=x1;x<=x2;x++)
{
for(int y=y1;y<=y2;y++)
{
dpixel(x,y,color);
}
}
}
void dclear(void)
{
for(int i = 0;i<395;i++){
for(int j=0;j<223;j++){
for(int i = 0;i<DWIDTH;i++){
for(int j=0;j<DHEIGHT;j++){
dpixel(i,j,0xffff);
}
@ -43,35 +55,36 @@ void dimage(int x, int y, image_t *image)
}
}
}
void pchar(int x, int y, char ch)
void pchar(int x, int y, char ch, uint16_t color)
{
int index = (int)ch;
for(int i=0;i<8;i++){
for (int j=0;j<8;j++){
int offset_y = floor((8*index)/128);
int index2 = index - offset_y*16;
dpixel(x+j,y+i,font.pixels[j+(8*index2) +font.width*i+offset_y*font.width*8]);
if(font.pixels[j+(8*index2) +font.width*i+offset_y*font.width*8]==0) dpixel(x+j,y+i,color);
}
}
}
void dtext(int x, int y, char *str)
void dtext(int x, int y, char *str, uint16_t color)
{
int i = 0;
while(1)
{
pchar(x,y,str[i++]);
pchar(x,y,str[i++], color);
x+=8;
if (str[i]=='\0'){break;}
}
}
void dprintf(int x, int y, char *format, ...)
void dprintf(int x, int y, uint16_t color, char *format, ...)
{
va_list args;
va_start(args, format);
char str[512];
vsprintf(str, format, args);
dtext(x,y,str);
dtext(x,y,str, color);
va_end(args);
}
}
uint16_t vram[DWIDTH*DHEIGHT];

34
src/keyboard/keyboard.c Normal file
View File

@ -0,0 +1,34 @@
#include <omega/utils.h>
#include <stdbool.h>
uint8_t scan[12];
void keyboard_setup()
{
for(int i=0;i<12;i++)
{
scan[i] = 0;
}
}
void keyboard_refresh()
{
uint16_t *KEYSC = (void *)0xa44b0000;
for(int i=0; i<6;i++)
{
scan[i*2] = KEYSC[i]& 0xff;
scan[i*2+1] = KEYSC[i] >> 8;
}
}
uint8_t keyboard_get_line(int line)
{
return scan[line];
}
bool keydown(int key)
{
keyboard_refresh();
int row = (key >> 4);
int col = 0x80 >> (key & 0x7);
return (scan[row] & col) != 0;
}

View File

@ -3,20 +3,22 @@
#include <omega/core.h>
#include <omega/display.h>
#include <omega/utils.h>
#include <omega/keyboard.h>
extern image_t rick;
int main(){
while(1){
int y = 65;
int x = 88;
while(!keydown(KEY_SHIFT)){
dclear();
dimage(88,55,&rick);
int a = (12*60)/2;
dprintf(10,20,"int : %i , hex : %x",a,a);
dprintf(10,40,"str : %s", "~~ welcome to omega ~~");
if(keydown(KEY_DOWN)) y+=1;
if(keydown(KEY_UP)) y-=1;
if(keydown(KEY_LEFT)) x-=1;
if(keydown(KEY_RIGHT)) x+=1;
dimage(x,y,&rick);
dprintf(10,25,C_BLACK,"str : %s", "~~ welcome to omega ~~");
dupdate();
}
return 1;
}

View File

@ -56,15 +56,10 @@ void rframe(uint16_t xmin, uint16_t xmax, uint16_t ymin, uint16_t ymax)
rdirectwrite(ram_address_vertical,0);
}
void rsetup(void)
{
rframe(0,396,0,224);
}
void rdisplay(uint16_t *vram)
{
rsetup();
rframe(0,DWIDTH-1,0,DHEIGHT-1);
rselect(write_data);
for(int i = 0; i < 396 * 224; i++)
for(int i = 0; i < DWIDTH * DHEIGHT; i++)
rwrite(vram[i]);
}

View File

@ -1,123 +1,133 @@
#include <omega/utils.h>
void reverse(char str[], int length)
{
int start = 0;
int end = length - 1;
while (start < end) {
char temp = str[start];
str[start] = str[end];
str[end] = temp;
end--;
start++;
}
}
// Implementation of citoa()
char* itoa(int num, char* str, int base)
{
int i = 0;
int isNegative = 0;
if (num == 0) {
str[i++] = '0';
str[i] = '\0';
return str;
}
if (num < 0 && base == 10) {
isNegative = 1;
num = -num;
}
while (num != 0) {
int rem = num % base;
str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
num = num / base;
}
if (isNegative)
str[i++] = '-';
str[i] = '\0';
reverse(str, i);
return str;
}
char * strcpy(char *strDest, const char *strSrc)
{
char *temp = strDest;
while((*strDest++=*strSrc++) != '\0');
return temp;
}
char * strcat(char *dest, const char *src)
{
char *rdest = dest;
while (*dest)
dest++;
while ((*dest++ = *src++)!= '\0');
return rdest;
}
size_t strlen(const char *str)
{
size_t len = 0;
while (str[len] != '\0') {
len++;
}
return len;
}
int vsprintf(char *buffer, char *format, va_list args)
{
int index = 0;
while (*format != '\0') {
if (*format == '%') {
format++;
char temp[20];
switch (*format) {
case 'i': {
int num = va_arg(args, int);
itoa(num,temp,10);
size_t len = strlen(temp);
for (size_t i = 0; i < len; i++) {
buffer[index++] = temp[i];
}
break;
}
case 'x': {
int num = va_arg(args, int);
itoa(num,temp,16);
size_t len = strlen(temp);
buffer[index++] = '0';
buffer[index++] = 'x';
for (size_t i = 0; i < len; i++) {
buffer[index++] = temp[i];
}
break;
}
case 's': {
char *str = va_arg(args, char *);
size_t len = strlen(str);
for (size_t i = 0; i < len; i++) {
buffer[index++] = str[i];
}
break;
}
default:
// for unsupported format
buffer[index++] = '%';
buffer[index++] = *format;
}
} else {
buffer[index++] = *format;
}
format++;
}
buffer[index] = '\0';
return index;
#include <omega/utils.h>
#include <stdint.h>
#include <omega/display.h>
void reverse(char str[], int length)
{
int start = 0;
int end = length - 1;
while (start < end) {
char temp = str[start];
str[start] = str[end];
str[end] = temp;
end--;
start++;
}
}
// Implementation of citoa()
char* itoa(uint32_t num, char* str, int base)
{
int i = 0;
int isNegative = 0;
if (num == 0) {
str[i++] = '0';
str[i] = '\0';
return str;
}
if (num < 0 && base == 10) {
isNegative = 1;
num = -num;
}
while (num != 0) {
int rem = num % base;
str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
num = num / base;
}
if (isNegative)
str[i++] = '-';
str[i] = '\0';
reverse(str, i);
return str;
}
char * strcpy(char *strDest, const char *strSrc)
{
char *temp = strDest;
while((*strDest++=*strSrc++) != '\0');
return temp;
}
char * strcat(char *dest, const char *src)
{
char *rdest = dest;
while (*dest)
dest++;
while ((*dest++ = *src++)!= '\0');
return rdest;
}
size_t strlen(const char *str)
{
size_t len = 0;
while (str[len] != '\0') {
len++;
}
return len;
}
int vsprintf(char *buffer, char *format, va_list args)
{
int index = 0;
while (*format != '\0') {
if (*format == '%') {
format++;
char temp[20];
switch (*format) {
case 'i': {
uint32_t num = va_arg(args, uint32_t);
itoa(num,temp,10);
size_t len = strlen(temp);
for (size_t i = 0; i < len; i++) {
buffer[index++] = temp[i];
}
break;
}
case 'x': {
int num = va_arg(args, int);
itoa(num,temp,16);
size_t len = strlen(temp);
buffer[index++] = '0';
buffer[index++] = 'x';
for (size_t i = 0; i < len; i++) {
buffer[index++] = temp[i];
}
break;
}
case 's': {
char *str = va_arg(args, char *);
size_t len = strlen(str);
for (size_t i = 0; i < len; i++) {
buffer[index++] = str[i];
}
break;
}
default:
// for unsupported format
buffer[index++] = '%';
buffer[index++] = *format;
}
} else {
buffer[index++] = *format;
}
format++;
}
buffer[index] = '\0';
return index;
}
/* Copy data of size s from one address l to another address r*/
void memcpy(uint32_t * l, uint32_t * r, int32_t s)
{
while(s > 0)
{
*r++ = *l++;
s -= 4;
}
}