Introduction:
A while back I started a project called AsylumOS for the TI83+, and only managed to get basic GUI functions working before I lost all interest in TI programming altogether and began my descent into OS development for pc. Now, almost 2 years since writing my last line of Z80 code, I've decided to rejoin the community and raise AsylumOS from the dead.
During my departure I learned both and the difference between C and C++, gained a lot more experience in file system and multi/inter-process management, and picked up a bunch of neat tricks.

Changes:

Code:
1. All code will be written from scratch since the source to the old AsylumOS was lost.

2. All code will be self-written with an extreme focus on speed


Current Plans:

Code:
1. Will optionally use Yaz0 and/or RLE compression for file data. Yaz0 is a type of compression commonly used by Nintendo that combines RLE and LZ encoding.

2. Will include hooks for 4-level grayscale, 3d, and possibly both interrupts. The latter will be attempted, but I know it's highly unlikely if I intend to include perspective-corrected texture interpolation (which I do). Affine interpolation will also be supported.

3. Will make use of an internal module-relocation table. These can be executed by normal or safe kernel calls (used for exception handling) or can be relocated to RAM by the application to increase execution speed.

4. Asylum ≠a≠p≠p≠l≠i≠c≠a≠t≠i≠o≠n≠s≠ programs will be composed of text/data sections. The text section will be copied to RAM upon execution, but the data section will remain in archive memory accessible either through relocation or kernel calls.



This thread is mainly to post updates as the project progresses, but any suggestions, ideas, and tips are welcome.

Project Start Date: 03/16/12 3:45 am
Quote:
1. Will optionally use Yaz0 and/or RLE compression for file data. Yaz0 is a type of compression commonly used by Nintendo that combines RLE and LZ encoding.

2. Will include hooks for 4-level grayscale, 3d, and possibly both interrupts. The latter will be attempted, but I know it's highly unlikely if I intend to include perspective-corrected texture interpolation (which I do). Affine interpolation will also be supported.


Honestly, these sound like things you wouldn't (and really shouldn't) worry about this early in the process; I don't think AHelper's GlassOS even started implementing grayscale at all until 8 months into the WIP Alpha, and that was after the kernel was completely done and most other things were pretty much done as well. As for comparison to my NucleoOS, I'm about a month into working on it, and I'm still stuck on making efficient multiprocessing, and I'm not even finished with the filesystem yet.

As for some questions, what is your plan for the filesystem? I assume it'll be based on something simple like FAT12/16? As for multiprocessing, how many processes are you planning on supporting at one time (or, is it a monoprocessing kernel, like TI-OS?) If you're going the former way, I suggest copying to Flash for the text and the data sections, since worst case you have 3*(2^14) bytes of RAM to work with, which you'll probably want for kernel scratch space, the heap, and the stacks and such for all the processes. Also keep in mind, relocating to RAM may speed up process execution over time (since instead of switching flash pages, you switch between at most 3 RAM pages), but it'll definitely tie up the dispatcher, making process startup very CPU needy. Either way has its pros and cons, and it's up to you to decide which meets your kernel model better.
Ashbad wrote:
Quote:
1. Will optionally use Yaz0 and/or RLE compression for file data. Yaz0 is a type of compression commonly used by Nintendo that combines RLE and LZ encoding.

2. Will include hooks for 4-level grayscale, 3d, and possibly both interrupts. The latter will be attempted, but I know it's highly unlikely if I intend to include perspective-corrected texture interpolation (which I do). Affine interpolation will also be supported.


Honestly, these sound like things you wouldn't (and really shouldn't) worry about this early in the process; I don't think AHelper's GlassOS even started implementing grayscale at all until 8 months into the WIP Alpha, and that was after the kernel was completely done and most other things were pretty much done as well. As for comparison to my NucleoOS, I'm about a month into working on it, and I'm still stuck on making efficient multiprocessing, and I'm not even finished with the filesystem yet.

As for some questions, what is your plan for the filesystem? I assume it'll be based on something simple like FAT12/16? As for multiprocessing, how many processes are you planning on supporting at one time (or, is it a monoprocessing kernel, like TI-OS?) If you're going the former way, I suggest copying to Flash for the text and the data sections, since worst case you have 3*(2^14) bytes of RAM to work with, which you'll probably want for kernel scratch space, the heap, and the stacks and such for all the processes. Also keep in mind, relocating to RAM may speed up process execution over time (since instead of switching flash pages, you switch between at most 3 RAM pages), but it'll definitely tie up the dispatcher, making process startup very CPU needy. Either way has its pros and cons, and it's up to you to decide which meets your kernel model better.


Replying to your comment on grayscale first, I'm worrying about it now because I intend for all the GUI components to be in grayscale. I'm also worrying about compression now because I intend to use it in the filesystem and possibly to compress some of the data in the kernel itself like images or modules. If my memory serves me right I recreated the DCS stack functions in the old Asylum in just a few days, and although my z80 knowledge has greatly declined I doubt it'll be long before I can do it again. But generally, this is just a list of future plans/goals.
BTW, I made a typo, I meant to say 'programs' instead of 'applications'. Obviously, that'd be just stupid to even think about running apps in RAM XD

For the filesystem, I was thinking about implementing FAT16, but that seems pretty wasteful trying to divide memory into sectors, and I'm almost guaranteed to need a few more fields for Asylum-specific data. My worst fear though is speed since my #1 goal this time around is making Asylum as fast as humanly possible. Then again I could always strip down to the bare essentials...Idk, I might just end up designing my own filesystem.

For multithreading, I'm thinking about assigning each thread it's own stack with a limit and creating a 16-byte buffer for each thread to store the values of AF, BC, DE, HL, IX, IY, SP, and PC. An interrupt breaks program control, stores the values to the buffer, and begins executing some code in the other thread. To prevent some issues, I might also assign each thread its own address space so two processes don't accidentally overwrite each other's data. If I come up with a more efficient method later, I'll use it instead.
Quote:
Replying to your comment on grayscale first, I'm worrying about it now because I intend for all the GUI components to be in grayscale. I'm also worrying about compression now because I intend to use it in the filesystem and possibly to compress some of the data in the kernel itself like images or modules. If my memory serves me right I recreated the DCS stack functions in the old Asylum in just a few days, and although my z80 knowledge has greatly declined I doubt it'll be long before I can do it again. But generally, this is just a list of future plans/goals.
BTW, I made a typo, I meant to say 'programs' instead of 'applications'. Obviously, that'd be just stupid to even think about running apps in RAM XD


Again, you shouldn't be worrying about this right now. Unless you're starting with another kernel already, and the low level aspects are all worked out. Trust me, the non-visual components of the OS can't really come together before the parts.

Quote:
For multithreading, I'm thinking about assigning each thread it's own stack with a limit and creating a 16-byte buffer for each thread to store the values of AF, BC, DE, HL, IX, IY, SP, and PC. An interrupt breaks program control, stores the values to the buffer, and begins executing some code in the other thread. To prevent some issues, I might also assign each thread its own address space so two processes don't accidentally overwrite each other's data. If I come up with a more efficient method later, I'll use it instead.


Fair enough, sounds pretty standard for a simple multiprocessing design. Any ideas for the [url=http://en.wikipedia.org/wiki/Scheduling_(computing)]scheduler[/url]?
Your right; I just like to brainstorm Smile
Right now I just got the basic kernel setup; turning on & off the lcd and detecting keypresses. Haven't worked on it much yet, I've been spending most of my time trying to find a good guide for screwing around with various ports and the specific timings/delays required. Wikiti's pretty good, but it doesn't go into detail with things like how many cycles are needed between reading and writing the lcd port.

For processor scheduling, I'll probably use a single-byte counter that gets shifted each interrupt and when it sets the carry flag I'll switch the thread. I figure that on a TI83+ that'd change the thread about once every second.
As far cpu usage goes, I'll just give the active thread no less than 50% of the processing time and divide the rest among the remaining threads; that way the active thread is always faster.

eg. If only 1 thread is being used, then no thread switching will occur.
If 2 threads are open, then the active thread will execute for 1 second then the second thread for 1 second.
If 3 threads are open, then the active thread will execute for 2 seconds, the second thread for 1 seconds, and then the third for 1 second.

The max would be about 4 threads and I might add the ability to pause thread execution.
A 1 second timeslice? That seems rather large to me, considering you may be running two real-time games at the same time, and each game needs constant CPU time to work effectively. With delays like that, the throughput of the processes will be fantastic, but the Latency will most definitely suffer. Of course, christop's Punix apparently uses a scheduling technique called "Brain F*** scheduling" that he gets decent performance from even with such large timeslices.

As for a question, I'm not completely sure what you mean by this:

Quote:
eg. If only 1 thread is being used, then no thread switching will occur.
If 2 threads are open, then the active thread will execute for 1 second then the second thread for 1 second.
If 3 threads are open, then the active thread will execute for 2 seconds, the second thread for 1 seconds, and then the third for 1 second.


What is an "active thread"? The one currently using the CPU? If so, how could the other threads even process during this time? You see, you can physically only run one thread at a time, since you only have a single CPU at your disposal. The way you should be differentiating the amount of time each process gets to use the system up for is by using a "fairness" technique. For example, some of them are FIFO (literally just using a queue of processes to run), Priority-based (timeslice length depends on priority level), and Round Robin (same amount of time for each process, get CPU time one after the other, and once the last one in the list gets its time, it repeats to the first). For example, NucleoOS uses a very simple mix between Priority-based and Round Robin scheduling (robin-robin fashion, but process interrupting by events and timeslices depend on relative priorities).

As for the LCD ports, I think I'll share some code from NucleoOS's built-in LCD driver:


Code:
LCD_WAIT:
   push af
   @
      in a, (PORT_LCD_COMMAND)
      and LCD_CMD_MASK_LCDBUSY
      cp 0
      jp nz, {-1@}
   pop af
   ret
LCD_WAIT_END:


Where LCD_CMD_MASK_LCDBUSY is %10000000, and PORT_LCD_COMMAND is $10. This will provide a sufficient wait until the LCD becomes ready to send a command/byte of data again, but can also be done using ports $20 and $2F, or $29-$2C. I use the checking delay instead, though, not the waiting ports.

And of course, cheers for the hard work ahead! It can be very painful at times to write a Kernel from scratch, as I have so far found out; however, I've learned a lot already from writing NucleoOS, as I'm sure you will too. It's already turned out to be one of the more rewarding and fun projects I've taken on .
the thread of the progam that the user is focused on is the active thread.
Anakclusmos wrote:
the thread of the progam that the user is focused on is the active thread.


What exactly do you mean by that? How will the user focus on processes?
my idea was to add an on key handler to the interrupt that bring up the currently running processes, kinda like the alt-tab shortcut on pc. although other processes can run in the background, most of the processing time is devoted to the program the user is focused on, in short semi-priority based processor scheduling.

thanks for the lcd driver tip Smile question though, does pulling the lcd state work on all ti83+ models? and what are the timings?

edit:
i might mask the thread counter with 0x88 instead
Anakclusmos wrote:
thanks for the lcd driver tip Smile question though, does pulling the lcd state work on all ti83+ models? and what are the timings?


For each model and LCD hardware it's different, so pulling bit 7 from $10 and checking that is a surefire way to wait the correct length. And, AFAIK, the way I gave the code for works on all 83+-84+ models. Not sure about the other ports, though (like $20, $29, $2F, etc. someone more experienced can clear that up for us though)
I'm thinking I should change AsylumOS LE to a shell project instead of an os project. As an os, hardly anyone would use it and it'd be done almost entirely for self-satisfaction.

Yes/No?
Anakclusmos wrote:
I'm thinking I should change AsylumOS LE to a shell project instead of an os project. As an os, hardly anyone would use it and it'd be done almost entirely for self-satisfaction.

Yes/No?


That could be argued as true, but the self-satisfaction is far less a benefit than the learning you would go through to make this.
I wouldn't learn much of anything really, I just came back from pc os-dev. Compared to having to setup global descriptor tables, interrupt vector tables, paging, writing a virtual filesystem manager, setting graphics modes, and loading ELF files, this is an enormous step backward for me.

Which re-boils it down to being done purely for self-satisfaction. Anyway, that's one 'No', lets if anyone else has an opinion. Kinda unlikely considering you're the only one who's replied to this thread so far Sad
Anakclusmos wrote:
I'm thinking I should change AsylumOS LE to a shell project instead of an os project. As an os, hardly anyone would use it and it'd be done almost entirely for self-satisfaction.

Yes/No?
That's true of every OS project, from PongOS to the now-dead KnightOS to CepticOS to GlassOS to (sadly) OS2. The issue is whether you'll get enough personal happiness and a sense of accomplishment from building it as an OS anyway, as you said.
Anakclusmos wrote:
I wouldn't learn much of anything really, I just came back from pc os-dev. Compared to having to setup global descriptor tables, interrupt vector tables, paging, writing a virtual filesystem manager, setting graphics modes, and loading ELF files, this is an enormous step backward for me.


I disagree. I actually think it's a wonderful learning experience; making a kernel for such a limited platform is a great way to learn some cool new OS dev tricks, how to make something semi-modern for an ancient embedded platform, and how to work under very limited constraints.
Kerm: You just confirmed my fears, I'm now scared shitless... :S

Ashbad: I'll agree with your first two statements completely, and I'm honestly not trying to being a dunce about saying this, but if you had seen some of my ideas you'd notice that I go above and beyond the extreme limits to ensure that my code and/or file formats are as compact as possible and that pretty much every bit has a purpose. Once primary example is my design of a 3d file format that uses a single sine value (as a half-float (16-bit float)) and the length of one edge to store the shape of faces rather than indices to vertices or the use of vertices period. I'm simplifying the explanation here, but the overall point is that I have a bad habit of constraining myself for no obvious reason at all to the point of it just seeming stupid.
Two other examples of my habit of over-complicating and/or heavily constraining myself are my z80 GetCSC checkkey routine that's like 10 lines long and the PushGUIStacks / FindGUI routines currently used in DCS7. (they were first used as subroutines in a text-editting DCS6 program I was working on, and Kerm liked 'em so he made some improvements and added them in DCS7)
Continuing with yet another example, I wrote an entire library for reading Blender 3d files (non-compressed) that requires no memory allocations whatsoever; all functions are performed on the open file.
You can trust me when I say I am very good at working under very limited constraints Very Happy



EDIT:
I had some free time and figured I'd share more about the afore-mentioned 3d model format I was working on. Normally, 3d model formats store 4 types of data: vertices, normals, uvs, and faces (this is excluding skinned models). Basically, my idea works like this:

Quote:
* Each face uses a sine value and the length of one of the edges.

* Since sine is calculated by the length of the side opposite of an angle divided by the length of the hypotenuse (B/C), the length of the hypotenuse is calculated by multiplying the reciprocal of the sine value by the length of the one side.

* The reverse of the Pythagorean Theorem is (C²-B²=A²) is used to calculate the length of the remaining side.

* The value of the largest angle is calculated by the equation cos⁻¹((A²+B²-C²)/(2AB))

* Calculate the next angle with the equation sin(A*sin(X)/C) where 'X' is the first angle we found.

* Calculate the 3rd angle by subtracting the first 2 angles we found from 180.

--------------------------------------
Now we have the length of each side of the face and the values of each of it's angles. I use either a half-float or 16-bit fixed point values for the sine and length of the one side, meaning that we've pretty much managed to store 3 lengths and 3 angles with only 4 bytes.
--------------------------------------

* Each face also has an x/y/z rotation and x/y/z location. For these, I (again) use either half-floats or 16-bit fixed point values. In addition to positioning the face, the x/y/z rotation can be used to calculate the normals for the face.

* Finally, like the faces themselves, the uv coords of uv-mapped faces are stored in the sine/length fashion with 2 u16's for the position. This allows for exact pixel coordinates for image sizes up to 65535x65535 while still saving 4 bytes.


Wrapping up, this new format stores the locations and normals normals of 3 vertices and the actual shape of the face itself with only 16-bytes, or 24 bytes if it's textured.
That's kinda amazing when you consider that most 3d file formats use 12-24 bytes just to store the location of 1 vertex (not including normals or uv coords).

---------------------------


EDIT2:

I made a mistake when I wrote how to calculate the second angle using the first. I fixed that, and here's an example for a face whose sine value is 0.6 and edge length is 3.

0.6 = 6/10
reciprocal(6/10) = 10/6 = 1.66667 (1 2/3)
1.66667 * length (3) = 5
sqrt((5*5)-(3*3)) = 4
cos⁻¹((3²+4²-5²)/(2*3*4)) = 90
sin(3sin(90)/5) = 36.87
180 - 90 - 36.87 = 53.13


side A length = 3
side B length = 4
hypotenuse length = 5
angle 1 is 90°
angle 2 is 36.87°
angle 3 is 53.13°
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement