Difference between revisions of "Caruh"
(→Language - Hotkey: l or L - Select your language for Tasks) |
(→Examples) |
||
(13 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
Caruh - the Multitasking-Manager for [[FutureOS]] | Caruh - the Multitasking-Manager for [[FutureOS]] | ||
− | = | + | = Overview = |
− | == | + | == General information == |
The ''''Caruh'''' application is part of the [[FutureOS]] operating system. Caruh is a tasker, that's a multitasking manager. Or rather, a program to run several applications (tasks) at the same time on the CPC. The individual 'Tasks' can behave cooperatively. | The ''''Caruh'''' application is part of the [[FutureOS]] operating system. Caruh is a tasker, that's a multitasking manager. Or rather, a program to run several applications (tasks) at the same time on the CPC. The individual 'Tasks' can behave cooperatively. | ||
Line 17: | Line 17: | ||
* Each task has its own 16 KB expansion RAM (E-RAM). These E-RAMs are banked in between &4000 and &7FFF. Accordingly a task is always assembled at the start address &4000. | * Each task has its own 16 KB expansion RAM (E-RAM). These E-RAMs are banked in between &4000 and &7FFF. Accordingly a task is always assembled at the start address &4000. | ||
− | == | + | == Types of Tasks == |
There are foreground and background tasks. A background task can be switched to be a foreground task by the user - if the task allows this (is capable of). | There are foreground and background tasks. A background task can be switched to be a foreground task by the user - if the task allows this (is capable of). | ||
Line 52: | Line 52: | ||
Caruh itself checks for ESC. But the task must / should do that too. | Caruh itself checks for ESC. But the task must / should do that too. | ||
− | = | + | = Using the Tasker Caruh = |
− | + | == Submenu File == | |
− | == | + | |
=== Load <T>ask - Hotkey: t or T - To load and start a Task === | === Load <T>ask - Hotkey: t or T - To load and start a Task === | ||
This function is to load a Task of a maximum file size of 16 KB. | This function is to load a Task of a maximum file size of 16 KB. | ||
Line 138: | Line 137: | ||
Any Task can read which language was selected. But Caruh itself will not change its language texts, because this would waste too much main memory. Caruh can be obtained in any (of the above) languages. See downloads. | Any Task can read which language was selected. But Caruh itself will not change its language texts, because this would waste too much main memory. Caruh can be obtained in any (of the above) languages. See downloads. | ||
− | == | + | == Submenu Tasks == |
=== '''S'''tart Task - Hotkey: s or S - To load and Start a Task === | === '''S'''tart Task - Hotkey: s or S - To load and Start a Task === | ||
See 'Load '''T'''ask' above | See 'Load '''T'''ask' above | ||
Line 151: | Line 150: | ||
See 'G'''o''' To' above | See 'G'''o''' To' above | ||
− | == | + | == Submenu Help == |
=== '''H'''elp - Hotkey: h or H - Show a help screen === | === '''H'''elp - Hotkey: h or H - Show a help screen === | ||
Just a little help screen. | Just a little help screen. | ||
Line 170: | Line 169: | ||
Here is your gateway the the [http://www.FutureOS.de FutuerOS homepage] which does support Caruh too :-) | Here is your gateway the the [http://www.FutureOS.de FutuerOS homepage] which does support Caruh too :-) | ||
+ | = Construction of Caruh = | ||
+ | == Memory allocation of the Caruh application in the lower RAM == | ||
+ | Caruh's program code starts in the RAM at &0000 and currently extends to &2000. | ||
+ | From address &3800 the character set is up to &3FFF (as usual). | ||
+ | So there are still about 5-6 KB available for future extensions of Caruh. | ||
+ | |||
+ | There are few variables in the lower RAM, as it's planned to integrate Caruh in a lower ROM one day. | ||
+ | |||
+ | However, there are some entries of OS functions being of interest for the Tasks and their programmer. | ||
+ | |||
+ | ==== Variables in Caruh ==== | ||
+ | * Memory address &000E contains the screen MODE (0-3) which was set by the user with the help of Caruh. Each task can read the desired (user set) screen mode from this byte in case the task is switched to the Foreground. | ||
+ | |||
+ | * Memory address &000F contains the user defined screen format. The format was set by the user using Caruh (0 for 80x25, 1 for 68x30 and 3 for 64x32 format). Each task can read the desired screen format from this byte if the task is switched to the Foreground. | ||
+ | |||
+ | ==== Entries in Caruh ==== | ||
+ | * The 'SAOMS' function can be called at RAM address &0003. It allows the user to reserve a part of the multi-screen (regular view). | ||
+ | |||
+ | * The menu system 'M_DISP2' known from CBM can be called at address &0008 with the command 'RST 1'. | ||
+ | |||
+ | * The window frame drawer 'DR_WIN' known from CBM can be called with using the command 'CALL &000B'. | ||
+ | |||
+ | * The function 'SEPRI' is called at address &0010 using the Z80 command 'RST 2'. Using 'SEPRI' a task can change its priority. Each task is started with the highest priority '1' after loading. Values from 1 to 255 are permitted. Smaller values have higher priority. | ||
+ | |||
+ | * The 'RFMSA' function is called at address &0013 using command 'CALL &0013'. 'RFMSA' is used to reserve a part of the shared screen for a Task. This means the view that can be seen after Caruh has started. The task is then allowed to write in this area. | ||
+ | == Memory allocation of the Caruh application in the central RAM == | ||
+ | The central RAM (main memory &7FC0) is occupied as follows from &4000 to &7FFF. | ||
+ | There are three RAM sections that are used for Task management: | ||
+ | |||
+ | * Task variables: these are contained in the first element of the task table or in the upper RAM | ||
+ | |||
+ | * Task table: this table contains one element for each task from 1-255 | ||
+ | |||
+ | * VRAM table: this table defines which task uses which part of the screen | ||
+ | |||
+ | ==== Task variables ==== | ||
+ | The Task variables are used by Caruh to manage the individual tasks, they show what's currently going on. | ||
+ | |||
+ | * &4000 (TASK_AKT): This byte points to the number of the current task that is currently active. | ||
+ | |||
+ | * &4001 (TASK_NUM): This byte contains the number of all existing tasks. | ||
+ | |||
+ | * &4002 (DIS_A_T): This byte contains the number of the first task in the Task bar in the lower line on screen. This means the left Task at the bottom line | ||
+ | |||
+ | * &400C/D (TA_ESEL): These 16 bits contain the I/O E-RAM select when a new task is loaded into the E-RAM of the computer. | ||
+ | |||
+ | * &400E/F (TA_OSEV): These 16 bits contain a pointer to one of the XRAM_?? variables when a new task is loaded into the E-RAM | ||
+ | |||
+ | * &4010: The first element of task #1 (16 bytes) starts at this address. In Caruh's source code this would be 'TT_START + T_T_E_L'. Whereby TT_START (= &4000) + T_T_E_L (= &0010) results in &4010! | ||
+ | |||
+ | * &7FE4-&7FFF: This area is required for Caruh itself (as task #1)! | ||
+ | |||
+ | In the upper RAM, two more bytes are used by Caruh! | ||
+ | They are used for communication between Caruh and the Tasks: | ||
+ | |||
+ | * &BE02 (CCON2): Central communication byte between Caruh and the Tasks | ||
+ | |||
+ | '''Structure of memory address &BE02 (CCON2)''' | ||
+ | |||
+ | Bit 0: = 0 -> All tasks are in the background (this is the normal state). In this case Caruh works as Foreground Task | ||
+ | |||
+ | Bit 0: = 1 -> A task is active in the foreground, i.e. takes over the screen, keyboard query, etc. This bit is switched on by the Task itself as soon as it has actively taken control of the complete screen etc. This bit MUST also be cleared by the Task itself as soon as it returns control of the screen (and keyboard) to Caruh. When you press the ESC key, the Task must return the control of screen and keyboard to Caruh. To do this, clear bit 0 at &BE02! | ||
+ | |||
+ | Bit 1: -> reserved | ||
+ | |||
+ | Bit 2: -> reserved | ||
+ | |||
+ | Bit 3: -> reserved | ||
+ | |||
+ | Bit 4: -> reserved | ||
+ | |||
+ | Bit 5: -> reserved | ||
+ | |||
+ | Bit 6: -> reserved | ||
+ | |||
+ | Bit 7: = 0 -> Caruh does not print on screen right now -> Tasks run as usual | ||
+ | |||
+ | Bit 7: = 1 -> Caruh prints text on the screen. For example it displays menus, provides selectors for files or options and so on. -> Tasks shall NOT use the screen as long as this bit is set! | ||
+ | |||
+ | * &BE03 (TTNS3): Temporary buffer for a Task number memory at &BE03. Stores the number of a task (2-255) for subroutines | ||
+ | |||
+ | === The Task Table === | ||
+ | The Task Table starts mathematically at &4000 in the main memory. | ||
+ | An entry in the Task Table is 16 bytes long. | ||
+ | Accordingly, it extends from &4000 to &4FFF in the central RAM (&7FC0). | ||
+ | |||
+ | However, the first element of the task table with number '0' has a special assignment: | ||
+ | Since there is no task with the number &00, the bytes &4000-&400F are available for the task variables (see above under 'Task variables'). | ||
+ | |||
+ | The first real element therefore starts at &4010 for the first task (#1). | ||
+ | |||
+ | '''Each element consists of 16 bytes: ''' | ||
+ | * 0: Task number (= number of the task managed by this entry) | ||
+ | * 1: Priority: How many 1/300 seconds are waited until the task will be called again. The value 0 is interpreted as 256. The smaller the value, the higher the task priority. | ||
+ | * 2: Reload value for the Priority byte, used as soon as the Priority byte has reached the value &00 (see previous byte 1) | ||
+ | * 3-4: These 16 bits contain the E-RAM select in which the task is located (16 bit, physical I/O address: &7FC4-&78FF, covers 4 MB) | ||
+ | * 5-15: The name of the Task, it corresponds to the file name (11 letters) | ||
+ | |||
+ | The data for Task #2 follows at address &4020, on &4030 for task #3, to &4040 for task #4 and so on ... | ||
+ | |||
+ | '''The VRAM / multi-screen table''' | ||
+ | |||
+ | As long as Caruh is active as a Foreground Task, other tasks can only use parts of the general screen. That's the screen that appears after starting Caruh with its menu system. | ||
+ | |||
+ | As long as the 'General Screen' is used, the following is possible: | ||
+ | |||
+ | * Each Task can reserve parts of the VRAM / general screen or itself. | ||
+ | * Each Task may write, draw or output data in any way on parts of the general screen (previously) reserved for it. | ||
+ | * No chaotic, overlapping windows are used! | ||
+ | |||
+ | This way it's possible for all Tasks to output data on the main screen. | ||
+ | This is the multi-screen mode. | ||
+ | |||
+ | The VRAM or multi-screen table is used to divide the screen (80 characters on 25 lines). This table comprises 2000 bytes (= 80 * 25). | ||
+ | |||
+ | The Table is located in the main memory from &7800 to &7FCF. | ||
+ | The bytes from &7FD0 to &7FFF are therefore NOT part of the Task Table. | ||
+ | |||
+ | Each byte of the VRAM (multi-screen) table corresponds to one character on the screen. | ||
+ | |||
+ | The VRAM Table begins with the first character in the top line on the far left. | ||
+ | That's followed by 'character by character' on the first line (left to right). | ||
+ | This is followed by 'line by line' from 'top to bottom'. | ||
+ | |||
+ | '''What's the meaning of the bytes in the VRAM table?''' | ||
+ | |||
+ | A zero byte in the VRAM Table defines an available/free screen position and is therefore available for Tasks. | ||
+ | |||
+ | If a byte in the Table is occupied by a value (1-255), then the corresponding position on the screen is already occupied by a Task. | ||
+ | |||
+ | Caruh occupies the top four lines and the bottom line of the screen for his own menu system and the lower Task Bar. | ||
+ | |||
+ | = Structure of a Task = | ||
+ | The entry / start / load address of each task is always at address &4000 | ||
+ | The file length may not exceed 16 KB (including a potential header!) | ||
+ | |||
+ | Each task occupies a 16 KB block (E-RAM block) from &4000 to &7EFF | ||
+ | The first 512 KB of expansion memory are currently being used for this. | ||
+ | However, the full 4 MB E-RAM should soon be used (-> Update2025) | ||
+ | |||
+ | == Structure of any Task within its 16 KB block == | ||
+ | * &4000-&7EFF: Program area -> Application length maximum 15.75 KB | ||
+ | * &7F00-&7FF7: Stack (each Task has its own Stack). Contains 124 elements | ||
+ | * &7FF8-&7FF9: (TCON8 and TCON9) 16 Action and Configuration bits. Please have a look at the following section :-) | ||
+ | * &7FFA-&7FFB: (TER16) 16 bit E-RAM selection of the Task (&7FC4-&78FF) | ||
+ | * &7FFC: (TAPRI) Value that is copied from the parttime/priority variable of the Task Table (if the priority is changed). (So how many 1/300 seconds is waited before the task is called.) It is the priority byte | ||
+ | * &7FFD: (TNUME) Number of this Task &01-&FF (255 Tasks are possible). The tasks are dynamic! (Variable name in Caruh: TNUME) | ||
+ | * &7FFE-&7FFF: (TSPSE) Buffer for the stack pointer SP of this Task. When switching Tasks, the register SP is also backed up | ||
+ | -> The program to be loaded (without header) is a maximum of &3F00 bytes long | ||
+ | -> The program to be loaded (with header) is a maximum of &3F80 bytes long | ||
+ | |||
+ | When a Task is started for the first time, its stack pointer SP is set to &7FF8. This is how the first 16-bit stack element is written to addresses &7FF6 and &7FF7. This is usually the return address when switching Tasks | ||
+ | |||
+ | === The action and configuration bits === | ||
+ | Memory locations &7FF8 / &7FF9 of each task contain 16 Action and Configuration bits. In addition there are Reaction bits that are set by the task: | ||
+ | |||
+ | ==== Memory address &7FF8 (TCON8) ==== | ||
+ | * Bits 1, 3, 4 and 6 are set by the task and | ||
+ | * Bits 2 and 7 are set by Caruh | ||
+ | * Bits 0 and 5 are manipulated by both Caruh and the task itself. | ||
+ | |||
+ | |||
+ | Bit 0: = 0 -> Task is in the Background (this is the regular state) | ||
+ | |||
+ | Bit 0: = 1 -> Task is active in the Foreground, i.e. takes over the screen, keyboard query etc. This bit is switched on by Caruh. It is / can be cleared by the task. (Foreground bit) | ||
+ | |||
+ | |||
+ | Bit 1: = 0 -> Task cannot become a Foreground Task | ||
+ | |||
+ | Bit 1: = 1 -> Task can be switched as a Foreground Task. This bit must be set by the Task itself! (Switch bit) | ||
+ | |||
+ | |||
+ | Bit 2: -> reserved | ||
+ | |||
+ | |||
+ | Bit 3: = 0 -> Regular function -> Task continues to work normally ... | ||
+ | |||
+ | Bit 3: = 1 -> Setting this bit determines the Task to be deleted! This bit is set by the Task itself! (Kill bit) | ||
+ | |||
+ | |||
+ | Bit 4: = 0 -> The Task cannot be saved or does not have to be specially prepared for it using 'Save Bit 7'. | ||
+ | |||
+ | Bit 4: = 1 -> This Task can be saved and should be prepared using bit 7. This bit is set by the Task itself! (Storable bit) | ||
+ | |||
+ | |||
+ | Bit 5: = 0 -> The Task has not yet been saved. | ||
+ | |||
+ | Bit 5: = 1 -> The Task was saved after the save bit was set. This bit 5 is set by the Caruh system after saving. (Hold bit 6 was previously set by the task itself). This bit 5 must be reset by the task itself if the task is to be saved several times. (Secured bit) | ||
+ | |||
+ | |||
+ | Bit 6: = 0 -> Task is still in progress -> do not save right now! Wait! | ||
+ | |||
+ | Bit 6: = 1 -> Task can now be saved by the system at any time! This bit must be set by the Task itself! (Hold bit) | ||
+ | |||
+ | |||
+ | Bit 7: = 0 -> Regular sequence. Task is running... | ||
+ | |||
+ | Bit 7: = 1 -> The system asks the Task to prepare for its saving. It is then restarted again at address &4000. (Save bit) | ||
+ | |||
+ | ==== Memory address &7FF9 (TCON9) ==== | ||
+ | * Reserved for future expansions | ||
+ | |||
+ | |||
+ | = V. Programming a Task = | ||
+ | In order to program a task, certain conventions must be observed. Strict rules apply here, which must be observed in every case. | ||
+ | However, Caruh also provides the Tasks with helpful functions. See later | ||
+ | |||
+ | === Task conventions: Requirements for Tasks === | ||
+ | * Tasks must retain their expansion RAM (E-RAM) configuration. Each task can read its own RAM banking status from addresses &7FFA and &7FFB. E.g. by an LD BC,(TER16). If illegal banking is still to be carried out, the interrupts must be switched off. | ||
+ | |||
+ | * Tasks must maintain the ROM / RAM status (the upper ROM is always on). For example, if data has to be read from the screen memory, the interrupts must be temporarily switched off. Note the status of the lower ROM! | ||
+ | |||
+ | * A Task can be a maximum of 15.75 KB long, because the stack of the Task and the Task variables are located above (see above: 'Structure of a task') | ||
+ | |||
+ | * Tasks do not require a header, as they are always loaded at address &4000. Tasks that have a header, including the header, must not be larger than 16 KB | ||
+ | |||
+ | * Tasks / files larger than 16 KB are NOT loaded / started by Caruh! | ||
+ | |||
+ | * A Task is allowed to output on screen only if in Caruh's Variable CCON2. (at address &BE02) the bits 0 and 7 are both cleared to zero. Exception: A Task did set bit 0 by himself, so its the Foreground-Task now | ||
+ | |||
+ | * During the call of OS functions that use hardware directly, the interrupts must be switched OFF and then switched ON again. The same is true if a Task used direct I/O hardware access. | ||
+ | |||
+ | * During the call of OS functions that use the stack pointer SP, the interrupts must be switched OFF and then switched ON again. Example: | ||
+ | |||
+ | DI ;switch off interrupts | ||
+ | |||
+ | CALL CUR_CPY ;Call OS function that changes SP | ||
+ | |||
+ | EI ;then switch on interrupts | ||
+ | |||
+ | |||
+ | '''Corresponding OS functions are in ROM A:''' | ||
+ | |||
+ | CUR_CPY | ||
+ | |||
+ | B8DIN | ||
+ | |||
+ | B16DIN | ||
+ | |||
+ | and all TERM_2 (?) OS functions (because of the control characters!) -> See the following ... | ||
+ | |||
+ | |||
+ | * The text output uses the OS variable C_POS to define the Cursor POSition. If a Task wants to output text, this variable must first be saved, then it must be set for the current text output (then output the text). Then C_POS must be restored again. During this time the interrupts must be switched off. Here's an example: | ||
+ | |||
+ | C_POS EQU &B848 | ||
+ | |||
+ | DI ;switch off interrupts | ||
+ | |||
+ | |||
+ | LD HL,(C_POS) ;Store old Cursor-POSition | ||
+ | |||
+ | LD (Buffer),HL | ||
+ | |||
+ | |||
+ | LD HL,&BFFF + (line * 80) + row ;Set new Cursor-POSition | ||
+ | |||
+ | LD (C_POS),HL | ||
+ | |||
+ | |||
+ | LD HL,Text ;Pointer to text | ||
+ | |||
+ | CALL TERM_2 ;Call OS function to print text on screen | ||
+ | |||
+ | LD HL,(Buffer) ;Restore old Cursor-POSition | ||
+ | |||
+ | LD (C_POS),HL | ||
+ | |||
+ | |||
+ | EI ;then switch on interrupts | ||
+ | |||
+ | |||
+ | * The OS ROM A must always be banked in / selected! If the ROM is changed or an OS function is called in the other OS ROMs B,C,D the interrupts must be switched OFF and then switched ON again. See example: | ||
+ | |||
+ | DI ;switch off interrupts | ||
+ | |||
+ | LD IX, LESC ;OS function is located in ROM C -> Load its name to IX | ||
+ | |||
+ | CALL ROM_A2C ;Call OS function in ROM C | ||
+ | |||
+ | EI ;then switch on interrupts again | ||
+ | |||
+ | |||
+ | * Cooperative Tasks can switch to the next task as long as they have nothing to do (e.g. waiting for an event, etc.) This is done through the commands: | ||
+ | |||
+ | DI ;disable interrupts | ||
+ | |||
+ | RST 7 ;call interrupt entry | ||
+ | |||
+ | |||
+ | The 'DI' command is required to counteract a simultaneous interrupt. | ||
+ | Without the 'DI' command the consequences could be fatal. | ||
+ | After processing the 'RST 7', the interrupts are switched on again. | ||
+ | The command sequence 'DI: RST 7' thus corresponds to a system interrupt. | ||
+ | |||
+ | * Each Task has to set some bits of the Action and Configuration bits itself. These are located in memory locations &7FF8 and &7FF9 (see above!). | ||
+ | |||
+ | * Tasks with full screen capability are able to use the entire screen. Such Tasks have set bit 1 (switch bit) of address &7FF8 in their E-RAM. All other tasks (e.g. without screen output) should delete this Switch bit. Every Foreground task should regularly check bit 0 (Foreground bit) ats &7FF8. Because if it's set, the entire screen is available to the Task. If the 'ESC' key is pressed, the Task should switch itself back to Background. This is done by deleting bit 0 at address &7FF8 in the E-RAM of the Task. | ||
+ | |||
+ | * If a Task wants to end itself and remove itself from the system, it sets the bit 3 (Kill bit). The system will delete the Task at times. | ||
+ | Specifically, this means that the task writes the value &08 to the address &7FF8 and can then call the task manager using 'DI: RST 7'. A jump to the previous 'DI' command should then follow. Example: | ||
+ | |||
+ | LOOP DI ;interrupts off, this is necessary before EVERY RST 7! | ||
+ | |||
+ | RST 7 ;Call Caruh (or next task) ... | ||
+ | |||
+ | JR LOOP ;waiting for the task to be terminated by Caruh | ||
+ | |||
+ | |||
+ | * Storable Tasks are Tasks that work together with the system to save a copy of themselves. To indicate to the system that it is a storable task, the Task independently sets bit 4 (Storable bit) at address &7FF8 in its own E-RAM. | ||
+ | Tasks that do not attach importance to being able to be saved should delete this bit 4 once when they are called the first time. | ||
+ | A storable Task should regularly check whether the system wants to save it now. This is the case when Caruh sets bit 0 (Save bit). | ||
+ | As soon as the Save bit has been set at address &7FF8, the task should take all necessary steps to prepare for saving. | ||
+ | If the task is ready to be saved, then it must set bit 6 (Hold bit) at the address &7FF8. | ||
+ | The Task is then saved, and Caruh takes care of this process. | ||
+ | As soon as the Task has been successfully saved by Caruh, Caruh sets bit 5 (Secured-Bit) at the Tasks E-RAM address &7FF8. | ||
+ | The Task now knows that it has been saved successfully. The Task now needs to reset the 'Secured Bit' and jump to address &4000. | ||
+ | Tasks saved by the Caruh system are loaded (like any other) to address &4000 and also started there. | ||
+ | |||
+ | = OS functions for Tasks = | ||
+ | The Tasker Caruh provides several additional OS functions for Tasks. | ||
+ | Furthermore, certain parameters can be queried from RAM variables. | ||
+ | Please refer to the chapter on Task variables above. | ||
+ | |||
+ | === Caruh's GUI and OS functions === | ||
+ | Both screen mode and screen format can be set by the user in Caruh. | ||
+ | This is done using options. | ||
+ | These settings can be read from the following RAM variables: | ||
+ | |||
+ | * Memory address &000E contains the screen mode (0-3) which was set by the user. Each task can read the desired screen mode from this byte if the Task is switched to the Foreground. | ||
+ | |||
+ | * Memory address &000F contains the screen format (0 for 80x25, 1 for 68x30 and 3 for 64x32 format) that was set by the user. Each Task can read the desired screen format from this byte if the Task is switched to the Foreground. | ||
+ | |||
+ | * MENU SYSTEM | ||
+ | The 'M_DISP2' menu system known from CBM can be called up with the 'RST 1' command. For parameter transfer see source code. | ||
+ | |||
+ | * DRAW WINDOW | ||
+ | The 'DR_WIN' window drawer known from CBM can be called with 'CALL &000B'. To call DR_WIN: | ||
+ | |||
+ | HL = Pointer to start of Parameter- and Text-Block | ||
+ | |||
+ | |||
+ | '''Such a data block looks like this:''' | ||
+ | |||
+ | DB LOCATE_YY ;Upmost line | ||
+ | |||
+ | DB LOCATE_XX ;Leftmost row | ||
+ | |||
+ | |||
+ | DB LINES ;Number of lines in Window-Frame | ||
+ | |||
+ | DB ROWS ;Number of rows / columns | ||
+ | |||
+ | |||
+ | DB "Sample text",&00 ;Text of first line, terminated by byte &00 | ||
+ | |||
+ | |||
+ | Now the text of the following lines may follow here... | ||
+ | |||
+ | Every line must be terminated by an &00 byte | ||
+ | |||
+ | A text line can use control codes for screen MODE 2 | ||
+ | |||
+ | As for example the locate control code (80x25 format): | ||
+ | |||
+ | DB &1F,YY,XX,"Text sample",&00 | ||
+ | |||
+ | |||
+ | '''ATTENTION:''' DR_WIN at &000B will switch the Interrupts OFF. The calling Task must switch them on again by itself. | ||
+ | |||
+ | |||
+ | * REQUEST SQUARE ON COMMON SCREEN SOMEWHERE | ||
+ | Calling the 'SAOMS' function at address &0003 allows the user to reserve a piece of the general multi-screen (regular view). | ||
+ | This OS function must be called by a Task. | ||
+ | |||
+ | |||
+ | '''To call this function:''' | ||
+ | |||
+ | Task number in TTNS3 = &BE03 (A Task can read its number from address TNUME = &7FFD) | ||
+ | |||
+ | YL = Total number of rows of area to be reserved (width, MODE 2 chars) | ||
+ | |||
+ | YH = Total number of lines of the area to be reserved (height) | ||
+ | |||
+ | |||
+ | '''Return from function:''' First you need to take a look at the Z-Flag, then see for data in XL and XH. | ||
+ | |||
+ | Z-Flag set '1' -> User Break using ESC key! Do not use values in IX! | ||
+ | |||
+ | Z-Flag cleared -> All fine! -> See registers XL and XH: XL = Upmost line / Y position of frame (0-24). XH = Leftmost raw / X position of Frame (0-79) | ||
+ | |||
+ | |||
+ | * REQUEST DEFINED SQUARE ON COMMON SCREEN ON DEFINED POSITION | ||
+ | |||
+ | If the 'RFMSA' function is called using the 'CALL &0013' command at address &0013, a Task can use it to reserve a part of the shared screen. The parameters are required as follows: | ||
+ | |||
+ | XL = Upmost line / Y position of frame (0-24) | ||
+ | |||
+ | XH = Leftmost raw / X position of Frame (0-79) | ||
+ | |||
+ | YL = Total Rows of Frame (1-80) | ||
+ | |||
+ | YH = Total Lines of Frame (1-25) | ||
+ | |||
+ | Address (TTNS3 = &BE03) = Number of requesting the Task | ||
+ | |||
+ | |||
+ | '''Return from function:''' When returning, the zero flag provides information about the success: | ||
+ | |||
+ | Z-Flag cleared -> Areas overlapping! Area can NOT be used! | ||
+ | |||
+ | Z flag set '1' -> Requested area CAN be used! | ||
+ | |||
+ | |||
+ | * SET PRIORITY OF A TASK | ||
+ | If the function 'SEPRI' is called using the Z80 command 'RST 2' at address &0010, a Task can change its priority (new priority in A). | ||
+ | Each task is started with the highest priority '1' after loading. | ||
+ | Often, however, a Task does not have to be called up that often (e.g. display time or temperature, send data to the printer, etc.). In such a case, the priority can be reduced. | ||
+ | The new priority is transferred in the accumulator; values from 1 to 255 are permissible. Smaller values have higher priority. | ||
+ | |||
+ | |||
+ | * If a task currently has nothing to do, it can actively switch to the next Task. This is done using the commands: | ||
+ | |||
+ | DI ;Disable interrupts (command before each 'RST 7' necessary!) | ||
+ | |||
+ | RST 7 ;Call up the Task Manager or the next Task | ||
+ | |||
+ | |||
+ | * Testing the content of address &7FFB on &7x allows integrity tests. Since the E-RAM status (high byte) is read here, the upper nibble must be '7'. If it's not equal to '7', the task E-RAM has been corrupted! | ||
+ | |||
+ | |||
+ | = Examples = | ||
+ | |||
+ | == Set a regular Background Task as the Foreground Task == | ||
+ | If any Background Task is made the only Foreground Task, then control of the | ||
+ | screen and keyboard scanning is passed to that new Foreground Task. | ||
+ | |||
+ | This is done either using the Task function 'Switch <t>o' of Caruh's menu or by clicking on one of the four Task names in the task bar (at the bottom of the screen). | ||
+ | |||
+ | This process cannot be initiated by the Task itself. However, if the user wants to switch a Task to the Foreground, this Task must also be able to react to it! | ||
+ | |||
+ | == Process log: A Background Task becomes a Foreground Task == | ||
+ | * Caruh reads and evaluates byte at memory location &7FF8 (TCON8) of the task: | ||
+ | |||
+ | If bit 1 is cleared, the task cannot become a Foreground Task! | ||
+ | |||
+ | If bit 1 is set, however, the task can be switched as a Foreground Task | ||
+ | |||
+ | * Caruh now sets bit 0 of memory location &7FF8 (TCON8) in the E-RAM of the Task to '1'. This tells the Task that it has now become the Foreground Task. The Task must now take control of the screen and the keyboard scanning. | ||
+ | |||
+ | * To inform Caruh that the Task has taken over screen control, the Task must set bit 0 in memory location &BE02 (CCON2). As soon as this bit is set, Caruh will relinquish screen control. | ||
+ | |||
+ | * At this point Caruh is now waiting for bit 0 to be set to '1' at address &BE02 (CCON2)! If that does not happen, Caruh will take over control again after a while (90 * DI: RST 7), as the Task appears incapable of doing so. | ||
+ | |||
+ | * As soon as bit 0 at address &BE02 (CCON2) is set to '1', Caruh waits for it to be reset in order to take control back again. See next paragraph | ||
+ | |||
+ | * The screen and keyboard are now available to the newly baked Foreground Task. Now it makes sense to first clear the screen, set the screen MODE 0-2 and possibly the screen format. | ||
+ | |||
+ | * The foreground task takes its course ... | ||
+ | |||
+ | * It's essential to test for 'ESCape' being pressed and to give control back to Caruh when the user's using the 'ESCape' key. | ||
+ | |||
+ | How does it work? | ||
+ | Continue reading please ... ;-) | ||
+ | |||
+ | == How can a Foreground Task return control to Caruh? == | ||
+ | When a Task has taken control of the screen and keyboard, it must also test whether the ESC key is pressed. If this is the case, control must be returned to Caruh. | ||
+ | The same applies if the Task simply wants to give back control. | ||
+ | |||
+ | * The Task deletes bit 0 at address &7FF8 (TCON8) in its own E-RAM. This turns the Task into a Background Task (regular state). But the Task also has to tell Caruh! This is how it happens ... | ||
+ | |||
+ | * The Foreground Task also deletes bit 0 at address &BE02 (CCON2)! | ||
+ | |||
+ | * As soon as bit 0 at address &BE02 (CCON2) is cleared, Caruh takes control of the screen and keyboard (as before). The former Foreground Task is now working in the Background again. | ||
+ | |||
+ | * Caruh is in the Foreground again :-) | ||
+ | |||
+ | |||
+ | '''Note:''' If the newly appointed Foreground Task is not able to set bit 0 of memory address &BE02 (CCON2) to 1, the Foreground status will be withdrawn after 192 cycles (192 times 'DI: RST 7')! | ||
+ | |||
+ | That means nothing else than that Caruh will take control again. | ||
+ | |||
+ | == Reserve parts of the common screen == | ||
+ | It's possible for each task to use certain parts of the general screen. | ||
+ | The position and extent of the claimed area are transferred. This request can be approved or rejected, depending on whether the claimed area is available. | ||
+ | This way it's possible for each task to always reserve the same sections for itself, since it can remember the coordinates of the first-time selection. | ||
+ | Either by saving the Task, using nvRAM or a configuration file. | ||
+ | |||
+ | The screen is divided into 80 columns (0-79) and 25 lines (0-24). | ||
+ | The table begins with the leftmost character on the top line. | ||
+ | |||
+ | When the Caruh system is started, Caruh reserves the first four lines (0-3) and | ||
+ | the bottom line (24). | ||
+ | |||
+ | |||
+ | This is how a Task can reserve a part of the general screen: | ||
+ | |||
+ | Entry (from the Task) at address &0003 | ||
+ | |||
+ | |||
+ | '''Parameter:''' | ||
+ | |||
+ | The number of the reserving Task is stored in TTNS3 = address &BE03 | ||
+ | |||
+ | The number of MODE 2 columns is transferred in register YL | ||
+ | |||
+ | The number of lines is transferred in register YH | ||
+ | |||
+ | The command 'LD IY, &0309' would therefore display 3 rows and 9 columns | ||
+ | |||
+ | |||
+ | * The current table is now graphically displayed on the screen. Only every 'empty' position can be assigned. A box - consisting of lines - can now be moved using the cursor keys and pressing Copy reserves the corresponding area of the screen and enters the position in the multi-screen Table. | ||
+ | |||
+ | * If the frame can't be set at the current position, the BORDER is shown in orange color (15). Either a valid area is found or the process can be canceled using the 'ESC' key. | ||
+ | |||
+ | * The Task is finally informed whether the setting of the frame was successful. | ||
+ | |||
+ | Furthermore, X (0-79 in XL) and Y (4-23 in XH) coordinates are transferred. These correspond to the left (XL) and upper (XH) corner on the screen. Register IX contains these two values. | ||
+ | |||
+ | In addition, the corresponding screen address of the top left corner is transferred (in RAM variable C_POS). | ||
Latest revision as of 11:38, 1 November 2023
Caruh - the Multitasking-Manager for FutureOS
Contents
- 1 Overview
- 2 Using the Tasker Caruh
- 2.1 Submenu File
- 2.1.1 Load <T>ask - Hotkey: t or T - To load and start a Task
- 2.1.2 Save Tas<k> - Hotkey: k or K - To save a Task
- 2.1.3 Load all - Hotkey: a or A - Loads and starts all tagged files as Tasks
- 2.1.4 Save tabl - Hotkey: s or S - Saves 16 KB Task-Table (--> for debugging)
- 2.1.5 Read DIRs - Hotkey: r or R - Reads the DIRs of all tagged drives
- 2.1.6 Close - Hotkey: c or C - End all Tasks. Quit this application
- 2.1.7 Version - Hotkey: v or V - Shows version number of Caruh
- 2.1.8 Quit - Hotkey: q or Q - End all Tasks. Quit this application
- 2.2 Submenu Process
- 2.3 Submenu Options
- 2.4 Submenu Tasks
- 2.5 Submenu Help
- 2.5.1 Help - Hotkey: h or H - Show a help screen
- 2.5.2 Info - Hotkey: i or I - Shows version number of Caruh (meanwhile)
- 2.5.3 News - Hotkey: n or N - Shows version number of Caruh (meanwhile)
- 2.5.4 Menu - Hotkey: m or M - Shows help about the used surface
- 2.5.5 -$$$- - Hotkey: $ or 4 - Tells how to spend money for this project
- 2.5.6 .www. - Hotkey: w or W - Tells where to find you in the internet
- 2.1 Submenu File
- 3 Construction of Caruh
- 4 Structure of a Task
- 5 V. Programming a Task
- 6 OS functions for Tasks
- 7 Examples
Overview
General information
The 'Caruh' application is part of the FutureOS operating system. Caruh is a tasker, that's a multitasking manager. Or rather, a program to run several applications (tasks) at the same time on the CPC. The individual 'Tasks' can behave cooperatively.
What properties does Caruh have or do the Tasks have?
- The Caruh application is located in the lower RAM between &0000 and &37FF. The area from &4000 to &7FFF is used in addition (for buffers, tables)
- Caruh works in screen MODE 2, in the 80 character x 25 line format
- CBM is used as the user interface: So Caruh can be used like to operate most other FutureOS applications.
- In addition to the pull-down menus at the top of the screen, there is another Task-Bar at the bottom of the screen. The names of four tasks are displayed there in the middle. With the arrows all the way left and right you can scroll horizontally through the names of the tasks
- The surface of Caruh offers functions to load, save, terminate or change the priority of one or more tasks
- The maximum number of different tasks is 255 (with a 4 MB RAM expansion)
- A task can reach a maximum size of 15.75 KB
- The tasks are managed dynamically. Task numbers can therefore change. For example, when a task is deleted, the higher task numbers are adjusted
- Each task has its own 16 KB expansion RAM (E-RAM). These E-RAMs are banked in between &4000 and &7FFF. Accordingly a task is always assembled at the start address &4000.
Types of Tasks
There are foreground and background tasks. A background task can be switched to be a foreground task by the user - if the task allows this (is capable of).
Foreground Tasks
A foreground task is able to take over the entire screen and to write on it. In addition he can also scan the keyboard.
He has to respond to the 'ESCape' key. In case the key was pressed then the task must return control back to Caruh.
Every foreground task is always also a background task (as long as it has not taken over the output to the screen).
Only the user can switch a background task to the foreground! There can only be one foreground task at a time!
Background Tasks
A background task is only allowed to write on the common screen. There he can reserve screen areas.
Summary
1. A task can be a (pure) background task
- He may reserve parts of the general screen and write on it
- He is not allowed to take over the entire screen
- It's identified by a cleared bit #0 at address &7FF8 (TCON8) in its E-RAM
2. A task can be switched to the 'foreground' by Caruh.
- There is always only one foreground task
- When starting Caruh, Caruh itself is the foreground task
- If another task becomes the 'Foreground Task', it's allowed to use the entire screen area. And the keyboard and the joysticks.
- However, he must also be able to give control back to Caruh at 'ESC'
- It's identified by a set bit 0 at address &7FF8 (TCON8) in E-RAM
Attention: To be able to switch a task to the foreground, bit 1 at address &7FF8 (TCON8) must be set. This is done by the task itself.
Pressing the 'ESCape' key must switch the task back to the background! Caruh itself checks for ESC. But the task must / should do that too.
Using the Tasker Caruh
Load <T>ask - Hotkey: t or T - To load and start a Task
This function is to load a Task of a maximum file size of 16 KB. The Task will be started right away.
Save Tas<k> - Hotkey: k or K - To save a Task
This function provides a way to save a 16 KB sized memory dump of a Task to any kind of media. Saving works in cooperation with the Task, so the Task can get prepared to be saved. A saved Task can be used to continue it later or on another computer (also it can be used for debugging purposes).
Load all - Hotkey: a or A - Loads and starts all tagged files as Tasks
This function can load a bunch of files as Tasks. Usually you would first mark all the Task-files in the FutureOS Turbo Destiop you would like to use. Then use this function to load and start them all. This way you can start up with a selection of your favorite Tasks at once.
Save tabl - Hotkey: s or S - Saves 16 KB Task-Table (--> for debugging)
This function actually saves 16 KB of the main RAM from &4000 to &7FFF. This area contains Task variables, the Task Table and the VRAM Table. Yes, this is for debugging purposes :-)
Read DIRs - Hotkey: r or R - Reads the DIRs of all tagged drives
Here you can select the drives / media / devices you want to use and load their DIRectories. This will make the devices accessible for Load and Save operations
Close - Hotkey: c or C - End all Tasks. Quit this application
This function will end and clear all Tasks, release the previously used E-RAM of the Tasks and end the Application Caruh.
Version - Hotkey: v or V - Shows version number of Caruh
This one will display the name of the application Caruh, its current version number and the date of the last major change of code.
Quit - Hotkey: q or Q - End all Tasks. Quit this application
See 'Close' above
Clear - Hotkey: l or L - Clear task = '<E>nd Task' (see below)
This function will end and clear a Task. The E-RAM of the Task will be released
Go To - Hotkey: o or L - Go To a Task = 'Switch <t>o' (see below)
This function will switch a Task to the Foreground, if the Task is able to do.
Call OS - Hotkey: a or A - Call the Desktop, return with the OK icon
Here the user can call the Turbo Desktop of FutureOS temporarily. In the Desktop you can f.e. tag some files or what every you want. But you must use the 'OK' Icon to return to the Task Manager Caruh.
Mode - Hotkey: m or M - Select the screen MODE 0-3 for Tasks
The user can select the screen mode for Tasks here. You can select MODEs 0-3. Yes, also MODE 3, which probably will not be used that often. However, the interface of Caruh will remain in MODE 2.
Colour - Hotkey: c or C - Select color for Pen, Paper or Border
The colors for BORDER, PAPER and PENs 0-15 can be selected here. This is valid for Caruh and all working Tasks.
Format - Hotkey: f or F - Select Task screen format (80x25, 64x32)
The screen format can be selected here for the Tasks. But it will not change the appearance of Caruh's interface itself.
Language - Hotkey: l or L - Select your language for Tasks
The language of FutureOS can be adjusted here. The selected language can be read from the configuration variable KF_CPC (at &B976) in bits 5, 4 and 3:
5,4,3 | 000 | OS language set to German |
5,4,3 | 001 | OS language set to French |
5,4,3 | 010 | OS language set to Englisch |
5,4,3 | 011 | OS language set to Greek |
5,4,3 | 100 | OS language set to Spanish |
5,4,3 | 101 | OS language set to Dutch |
Any Task can read which language was selected. But Caruh itself will not change its language texts, because this would waste too much main memory. Caruh can be obtained in any (of the above) languages. See downloads.
Start Task - Hotkey: s or S - To load and Start a Task
See 'Load Task' above
End Task - Hotkey: s or S - To end and delete a Task
See 'Clear' above
Priority - Hotkey: s or S - Set the Priority of a Task 1-255
This function can set the priority of any Task. 1 is the highest and 255 is the slowest. Basically this number tells how big the waiting time is 1/300 seconds
Switch to - Hotkey: t or T - Switch a Task to Foreground
See 'Go To' above
Help - Hotkey: h or H - Show a help screen
Just a little help screen.
Info - Hotkey: i or I - Shows version number of Caruh (meanwhile)
See 'Version' above
News - Hotkey: n or N - Shows version number of Caruh (meanwhile)
See 'Version' above
Menu - Hotkey: m or M - Shows help about the used surface
Some little help how to use the interface of Caruh. It's based on CBM framework
-$$$- - Hotkey: $ or 4 - Tells how to spend money for this project
Nobody ever did spend a Nickle for my work, so I'm not going into this here ;-)
.www. - Hotkey: w or W - Tells where to find you in the internet
Here is your gateway the the FutuerOS homepage which does support Caruh too :-)
Construction of Caruh
Memory allocation of the Caruh application in the lower RAM
Caruh's program code starts in the RAM at &0000 and currently extends to &2000. From address &3800 the character set is up to &3FFF (as usual). So there are still about 5-6 KB available for future extensions of Caruh.
There are few variables in the lower RAM, as it's planned to integrate Caruh in a lower ROM one day.
However, there are some entries of OS functions being of interest for the Tasks and their programmer.
Variables in Caruh
- Memory address &000E contains the screen MODE (0-3) which was set by the user with the help of Caruh. Each task can read the desired (user set) screen mode from this byte in case the task is switched to the Foreground.
- Memory address &000F contains the user defined screen format. The format was set by the user using Caruh (0 for 80x25, 1 for 68x30 and 3 for 64x32 format). Each task can read the desired screen format from this byte if the task is switched to the Foreground.
Entries in Caruh
- The 'SAOMS' function can be called at RAM address &0003. It allows the user to reserve a part of the multi-screen (regular view).
- The menu system 'M_DISP2' known from CBM can be called at address &0008 with the command 'RST 1'.
- The window frame drawer 'DR_WIN' known from CBM can be called with using the command 'CALL &000B'.
- The function 'SEPRI' is called at address &0010 using the Z80 command 'RST 2'. Using 'SEPRI' a task can change its priority. Each task is started with the highest priority '1' after loading. Values from 1 to 255 are permitted. Smaller values have higher priority.
- The 'RFMSA' function is called at address &0013 using command 'CALL &0013'. 'RFMSA' is used to reserve a part of the shared screen for a Task. This means the view that can be seen after Caruh has started. The task is then allowed to write in this area.
Memory allocation of the Caruh application in the central RAM
The central RAM (main memory &7FC0) is occupied as follows from &4000 to &7FFF. There are three RAM sections that are used for Task management:
- Task variables: these are contained in the first element of the task table or in the upper RAM
- Task table: this table contains one element for each task from 1-255
- VRAM table: this table defines which task uses which part of the screen
Task variables
The Task variables are used by Caruh to manage the individual tasks, they show what's currently going on.
- &4000 (TASK_AKT): This byte points to the number of the current task that is currently active.
- &4001 (TASK_NUM): This byte contains the number of all existing tasks.
- &4002 (DIS_A_T): This byte contains the number of the first task in the Task bar in the lower line on screen. This means the left Task at the bottom line
- &400C/D (TA_ESEL): These 16 bits contain the I/O E-RAM select when a new task is loaded into the E-RAM of the computer.
- &400E/F (TA_OSEV): These 16 bits contain a pointer to one of the XRAM_?? variables when a new task is loaded into the E-RAM
- &4010: The first element of task #1 (16 bytes) starts at this address. In Caruh's source code this would be 'TT_START + T_T_E_L'. Whereby TT_START (= &4000) + T_T_E_L (= &0010) results in &4010!
- &7FE4-&7FFF: This area is required for Caruh itself (as task #1)!
In the upper RAM, two more bytes are used by Caruh! They are used for communication between Caruh and the Tasks:
- &BE02 (CCON2): Central communication byte between Caruh and the Tasks
Structure of memory address &BE02 (CCON2)
Bit 0: = 0 -> All tasks are in the background (this is the normal state). In this case Caruh works as Foreground Task
Bit 0: = 1 -> A task is active in the foreground, i.e. takes over the screen, keyboard query, etc. This bit is switched on by the Task itself as soon as it has actively taken control of the complete screen etc. This bit MUST also be cleared by the Task itself as soon as it returns control of the screen (and keyboard) to Caruh. When you press the ESC key, the Task must return the control of screen and keyboard to Caruh. To do this, clear bit 0 at &BE02!
Bit 1: -> reserved
Bit 2: -> reserved
Bit 3: -> reserved
Bit 4: -> reserved
Bit 5: -> reserved
Bit 6: -> reserved
Bit 7: = 0 -> Caruh does not print on screen right now -> Tasks run as usual
Bit 7: = 1 -> Caruh prints text on the screen. For example it displays menus, provides selectors for files or options and so on. -> Tasks shall NOT use the screen as long as this bit is set!
- &BE03 (TTNS3): Temporary buffer for a Task number memory at &BE03. Stores the number of a task (2-255) for subroutines
The Task Table
The Task Table starts mathematically at &4000 in the main memory. An entry in the Task Table is 16 bytes long. Accordingly, it extends from &4000 to &4FFF in the central RAM (&7FC0).
However, the first element of the task table with number '0' has a special assignment: Since there is no task with the number &00, the bytes &4000-&400F are available for the task variables (see above under 'Task variables').
The first real element therefore starts at &4010 for the first task (#1).
Each element consists of 16 bytes:
- 0: Task number (= number of the task managed by this entry)
- 1: Priority: How many 1/300 seconds are waited until the task will be called again. The value 0 is interpreted as 256. The smaller the value, the higher the task priority.
- 2: Reload value for the Priority byte, used as soon as the Priority byte has reached the value &00 (see previous byte 1)
- 3-4: These 16 bits contain the E-RAM select in which the task is located (16 bit, physical I/O address: &7FC4-&78FF, covers 4 MB)
- 5-15: The name of the Task, it corresponds to the file name (11 letters)
The data for Task #2 follows at address &4020, on &4030 for task #3, to &4040 for task #4 and so on ...
The VRAM / multi-screen table
As long as Caruh is active as a Foreground Task, other tasks can only use parts of the general screen. That's the screen that appears after starting Caruh with its menu system.
As long as the 'General Screen' is used, the following is possible:
- Each Task can reserve parts of the VRAM / general screen or itself.
- Each Task may write, draw or output data in any way on parts of the general screen (previously) reserved for it.
- No chaotic, overlapping windows are used!
This way it's possible for all Tasks to output data on the main screen. This is the multi-screen mode.
The VRAM or multi-screen table is used to divide the screen (80 characters on 25 lines). This table comprises 2000 bytes (= 80 * 25).
The Table is located in the main memory from &7800 to &7FCF. The bytes from &7FD0 to &7FFF are therefore NOT part of the Task Table.
Each byte of the VRAM (multi-screen) table corresponds to one character on the screen.
The VRAM Table begins with the first character in the top line on the far left. That's followed by 'character by character' on the first line (left to right). This is followed by 'line by line' from 'top to bottom'.
What's the meaning of the bytes in the VRAM table?
A zero byte in the VRAM Table defines an available/free screen position and is therefore available for Tasks.
If a byte in the Table is occupied by a value (1-255), then the corresponding position on the screen is already occupied by a Task.
Caruh occupies the top four lines and the bottom line of the screen for his own menu system and the lower Task Bar.
Structure of a Task
The entry / start / load address of each task is always at address &4000 The file length may not exceed 16 KB (including a potential header!)
Each task occupies a 16 KB block (E-RAM block) from &4000 to &7EFF The first 512 KB of expansion memory are currently being used for this. However, the full 4 MB E-RAM should soon be used (-> Update2025)
Structure of any Task within its 16 KB block
- &4000-&7EFF: Program area -> Application length maximum 15.75 KB
- &7F00-&7FF7: Stack (each Task has its own Stack). Contains 124 elements
- &7FF8-&7FF9: (TCON8 and TCON9) 16 Action and Configuration bits. Please have a look at the following section :-)
- &7FFA-&7FFB: (TER16) 16 bit E-RAM selection of the Task (&7FC4-&78FF)
- &7FFC: (TAPRI) Value that is copied from the parttime/priority variable of the Task Table (if the priority is changed). (So how many 1/300 seconds is waited before the task is called.) It is the priority byte
- &7FFD: (TNUME) Number of this Task &01-&FF (255 Tasks are possible). The tasks are dynamic! (Variable name in Caruh: TNUME)
- &7FFE-&7FFF: (TSPSE) Buffer for the stack pointer SP of this Task. When switching Tasks, the register SP is also backed up
-> The program to be loaded (without header) is a maximum of &3F00 bytes long -> The program to be loaded (with header) is a maximum of &3F80 bytes long
When a Task is started for the first time, its stack pointer SP is set to &7FF8. This is how the first 16-bit stack element is written to addresses &7FF6 and &7FF7. This is usually the return address when switching Tasks
The action and configuration bits
Memory locations &7FF8 / &7FF9 of each task contain 16 Action and Configuration bits. In addition there are Reaction bits that are set by the task:
Memory address &7FF8 (TCON8)
- Bits 1, 3, 4 and 6 are set by the task and
- Bits 2 and 7 are set by Caruh
- Bits 0 and 5 are manipulated by both Caruh and the task itself.
Bit 0: = 0 -> Task is in the Background (this is the regular state)
Bit 0: = 1 -> Task is active in the Foreground, i.e. takes over the screen, keyboard query etc. This bit is switched on by Caruh. It is / can be cleared by the task. (Foreground bit)
Bit 1: = 0 -> Task cannot become a Foreground Task
Bit 1: = 1 -> Task can be switched as a Foreground Task. This bit must be set by the Task itself! (Switch bit)
Bit 2: -> reserved
Bit 3: = 0 -> Regular function -> Task continues to work normally ...
Bit 3: = 1 -> Setting this bit determines the Task to be deleted! This bit is set by the Task itself! (Kill bit)
Bit 4: = 0 -> The Task cannot be saved or does not have to be specially prepared for it using 'Save Bit 7'.
Bit 4: = 1 -> This Task can be saved and should be prepared using bit 7. This bit is set by the Task itself! (Storable bit)
Bit 5: = 0 -> The Task has not yet been saved.
Bit 5: = 1 -> The Task was saved after the save bit was set. This bit 5 is set by the Caruh system after saving. (Hold bit 6 was previously set by the task itself). This bit 5 must be reset by the task itself if the task is to be saved several times. (Secured bit)
Bit 6: = 0 -> Task is still in progress -> do not save right now! Wait!
Bit 6: = 1 -> Task can now be saved by the system at any time! This bit must be set by the Task itself! (Hold bit)
Bit 7: = 0 -> Regular sequence. Task is running...
Bit 7: = 1 -> The system asks the Task to prepare for its saving. It is then restarted again at address &4000. (Save bit)
Memory address &7FF9 (TCON9)
- Reserved for future expansions
V. Programming a Task
In order to program a task, certain conventions must be observed. Strict rules apply here, which must be observed in every case. However, Caruh also provides the Tasks with helpful functions. See later
Task conventions: Requirements for Tasks
- Tasks must retain their expansion RAM (E-RAM) configuration. Each task can read its own RAM banking status from addresses &7FFA and &7FFB. E.g. by an LD BC,(TER16). If illegal banking is still to be carried out, the interrupts must be switched off.
- Tasks must maintain the ROM / RAM status (the upper ROM is always on). For example, if data has to be read from the screen memory, the interrupts must be temporarily switched off. Note the status of the lower ROM!
- A Task can be a maximum of 15.75 KB long, because the stack of the Task and the Task variables are located above (see above: 'Structure of a task')
- Tasks do not require a header, as they are always loaded at address &4000. Tasks that have a header, including the header, must not be larger than 16 KB
- Tasks / files larger than 16 KB are NOT loaded / started by Caruh!
- A Task is allowed to output on screen only if in Caruh's Variable CCON2. (at address &BE02) the bits 0 and 7 are both cleared to zero. Exception: A Task did set bit 0 by himself, so its the Foreground-Task now
- During the call of OS functions that use hardware directly, the interrupts must be switched OFF and then switched ON again. The same is true if a Task used direct I/O hardware access.
- During the call of OS functions that use the stack pointer SP, the interrupts must be switched OFF and then switched ON again. Example:
DI ;switch off interrupts
CALL CUR_CPY ;Call OS function that changes SP
EI ;then switch on interrupts
Corresponding OS functions are in ROM A:
CUR_CPY
B8DIN
B16DIN
and all TERM_2 (?) OS functions (because of the control characters!) -> See the following ...
- The text output uses the OS variable C_POS to define the Cursor POSition. If a Task wants to output text, this variable must first be saved, then it must be set for the current text output (then output the text). Then C_POS must be restored again. During this time the interrupts must be switched off. Here's an example:
C_POS EQU &B848
DI ;switch off interrupts
LD HL,(C_POS) ;Store old Cursor-POSition
LD (Buffer),HL
LD HL,&BFFF + (line * 80) + row ;Set new Cursor-POSition
LD (C_POS),HL
LD HL,Text ;Pointer to text
CALL TERM_2 ;Call OS function to print text on screen
LD HL,(Buffer) ;Restore old Cursor-POSition
LD (C_POS),HL
EI ;then switch on interrupts
- The OS ROM A must always be banked in / selected! If the ROM is changed or an OS function is called in the other OS ROMs B,C,D the interrupts must be switched OFF and then switched ON again. See example:
DI ;switch off interrupts
LD IX, LESC ;OS function is located in ROM C -> Load its name to IX
CALL ROM_A2C ;Call OS function in ROM C
EI ;then switch on interrupts again
- Cooperative Tasks can switch to the next task as long as they have nothing to do (e.g. waiting for an event, etc.) This is done through the commands:
DI ;disable interrupts
RST 7 ;call interrupt entry
The 'DI' command is required to counteract a simultaneous interrupt.
Without the 'DI' command the consequences could be fatal.
After processing the 'RST 7', the interrupts are switched on again.
The command sequence 'DI: RST 7' thus corresponds to a system interrupt.
- Each Task has to set some bits of the Action and Configuration bits itself. These are located in memory locations &7FF8 and &7FF9 (see above!).
- Tasks with full screen capability are able to use the entire screen. Such Tasks have set bit 1 (switch bit) of address &7FF8 in their E-RAM. All other tasks (e.g. without screen output) should delete this Switch bit. Every Foreground task should regularly check bit 0 (Foreground bit) ats &7FF8. Because if it's set, the entire screen is available to the Task. If the 'ESC' key is pressed, the Task should switch itself back to Background. This is done by deleting bit 0 at address &7FF8 in the E-RAM of the Task.
- If a Task wants to end itself and remove itself from the system, it sets the bit 3 (Kill bit). The system will delete the Task at times.
Specifically, this means that the task writes the value &08 to the address &7FF8 and can then call the task manager using 'DI: RST 7'. A jump to the previous 'DI' command should then follow. Example:
LOOP DI ;interrupts off, this is necessary before EVERY RST 7!
RST 7 ;Call Caruh (or next task) ...
JR LOOP ;waiting for the task to be terminated by Caruh
- Storable Tasks are Tasks that work together with the system to save a copy of themselves. To indicate to the system that it is a storable task, the Task independently sets bit 4 (Storable bit) at address &7FF8 in its own E-RAM.
Tasks that do not attach importance to being able to be saved should delete this bit 4 once when they are called the first time. A storable Task should regularly check whether the system wants to save it now. This is the case when Caruh sets bit 0 (Save bit). As soon as the Save bit has been set at address &7FF8, the task should take all necessary steps to prepare for saving. If the task is ready to be saved, then it must set bit 6 (Hold bit) at the address &7FF8. The Task is then saved, and Caruh takes care of this process. As soon as the Task has been successfully saved by Caruh, Caruh sets bit 5 (Secured-Bit) at the Tasks E-RAM address &7FF8. The Task now knows that it has been saved successfully. The Task now needs to reset the 'Secured Bit' and jump to address &4000. Tasks saved by the Caruh system are loaded (like any other) to address &4000 and also started there.
OS functions for Tasks
The Tasker Caruh provides several additional OS functions for Tasks. Furthermore, certain parameters can be queried from RAM variables. Please refer to the chapter on Task variables above.
Caruh's GUI and OS functions
Both screen mode and screen format can be set by the user in Caruh. This is done using options. These settings can be read from the following RAM variables:
- Memory address &000E contains the screen mode (0-3) which was set by the user. Each task can read the desired screen mode from this byte if the Task is switched to the Foreground.
- Memory address &000F contains the screen format (0 for 80x25, 1 for 68x30 and 3 for 64x32 format) that was set by the user. Each Task can read the desired screen format from this byte if the Task is switched to the Foreground.
- MENU SYSTEM
The 'M_DISP2' menu system known from CBM can be called up with the 'RST 1' command. For parameter transfer see source code.
- DRAW WINDOW
The 'DR_WIN' window drawer known from CBM can be called with 'CALL &000B'. To call DR_WIN:
HL = Pointer to start of Parameter- and Text-Block
Such a data block looks like this:
DB LOCATE_YY ;Upmost line
DB LOCATE_XX ;Leftmost row
DB LINES ;Number of lines in Window-Frame
DB ROWS ;Number of rows / columns
DB "Sample text",&00 ;Text of first line, terminated by byte &00
Now the text of the following lines may follow here...
Every line must be terminated by an &00 byte
A text line can use control codes for screen MODE 2
As for example the locate control code (80x25 format):
DB &1F,YY,XX,"Text sample",&00
ATTENTION: DR_WIN at &000B will switch the Interrupts OFF. The calling Task must switch them on again by itself.
- REQUEST SQUARE ON COMMON SCREEN SOMEWHERE
Calling the 'SAOMS' function at address &0003 allows the user to reserve a piece of the general multi-screen (regular view). This OS function must be called by a Task.
To call this function:
Task number in TTNS3 = &BE03 (A Task can read its number from address TNUME = &7FFD)
YL = Total number of rows of area to be reserved (width, MODE 2 chars)
YH = Total number of lines of the area to be reserved (height)
Return from function: First you need to take a look at the Z-Flag, then see for data in XL and XH.
Z-Flag set '1' -> User Break using ESC key! Do not use values in IX!
Z-Flag cleared -> All fine! -> See registers XL and XH: XL = Upmost line / Y position of frame (0-24). XH = Leftmost raw / X position of Frame (0-79)
- REQUEST DEFINED SQUARE ON COMMON SCREEN ON DEFINED POSITION
If the 'RFMSA' function is called using the 'CALL &0013' command at address &0013, a Task can use it to reserve a part of the shared screen. The parameters are required as follows:
XL = Upmost line / Y position of frame (0-24)
XH = Leftmost raw / X position of Frame (0-79)
YL = Total Rows of Frame (1-80)
YH = Total Lines of Frame (1-25)
Address (TTNS3 = &BE03) = Number of requesting the Task
Return from function: When returning, the zero flag provides information about the success:
Z-Flag cleared -> Areas overlapping! Area can NOT be used!
Z flag set '1' -> Requested area CAN be used!
- SET PRIORITY OF A TASK
If the function 'SEPRI' is called using the Z80 command 'RST 2' at address &0010, a Task can change its priority (new priority in A). Each task is started with the highest priority '1' after loading. Often, however, a Task does not have to be called up that often (e.g. display time or temperature, send data to the printer, etc.). In such a case, the priority can be reduced. The new priority is transferred in the accumulator; values from 1 to 255 are permissible. Smaller values have higher priority.
- If a task currently has nothing to do, it can actively switch to the next Task. This is done using the commands:
DI ;Disable interrupts (command before each 'RST 7' necessary!)
RST 7 ;Call up the Task Manager or the next Task
- Testing the content of address &7FFB on &7x allows integrity tests. Since the E-RAM status (high byte) is read here, the upper nibble must be '7'. If it's not equal to '7', the task E-RAM has been corrupted!
Examples
Set a regular Background Task as the Foreground Task
If any Background Task is made the only Foreground Task, then control of the screen and keyboard scanning is passed to that new Foreground Task.
This is done either using the Task function 'Switch <t>o' of Caruh's menu or by clicking on one of the four Task names in the task bar (at the bottom of the screen).
This process cannot be initiated by the Task itself. However, if the user wants to switch a Task to the Foreground, this Task must also be able to react to it!
Process log: A Background Task becomes a Foreground Task
- Caruh reads and evaluates byte at memory location &7FF8 (TCON8) of the task:
If bit 1 is cleared, the task cannot become a Foreground Task!
If bit 1 is set, however, the task can be switched as a Foreground Task
- Caruh now sets bit 0 of memory location &7FF8 (TCON8) in the E-RAM of the Task to '1'. This tells the Task that it has now become the Foreground Task. The Task must now take control of the screen and the keyboard scanning.
- To inform Caruh that the Task has taken over screen control, the Task must set bit 0 in memory location &BE02 (CCON2). As soon as this bit is set, Caruh will relinquish screen control.
- At this point Caruh is now waiting for bit 0 to be set to '1' at address &BE02 (CCON2)! If that does not happen, Caruh will take over control again after a while (90 * DI: RST 7), as the Task appears incapable of doing so.
- As soon as bit 0 at address &BE02 (CCON2) is set to '1', Caruh waits for it to be reset in order to take control back again. See next paragraph
- The screen and keyboard are now available to the newly baked Foreground Task. Now it makes sense to first clear the screen, set the screen MODE 0-2 and possibly the screen format.
- The foreground task takes its course ...
- It's essential to test for 'ESCape' being pressed and to give control back to Caruh when the user's using the 'ESCape' key.
How does it work? Continue reading please ... ;-)
How can a Foreground Task return control to Caruh?
When a Task has taken control of the screen and keyboard, it must also test whether the ESC key is pressed. If this is the case, control must be returned to Caruh. The same applies if the Task simply wants to give back control.
- The Task deletes bit 0 at address &7FF8 (TCON8) in its own E-RAM. This turns the Task into a Background Task (regular state). But the Task also has to tell Caruh! This is how it happens ...
- The Foreground Task also deletes bit 0 at address &BE02 (CCON2)!
- As soon as bit 0 at address &BE02 (CCON2) is cleared, Caruh takes control of the screen and keyboard (as before). The former Foreground Task is now working in the Background again.
- Caruh is in the Foreground again :-)
Note: If the newly appointed Foreground Task is not able to set bit 0 of memory address &BE02 (CCON2) to 1, the Foreground status will be withdrawn after 192 cycles (192 times 'DI: RST 7')!
That means nothing else than that Caruh will take control again.
Reserve parts of the common screen
It's possible for each task to use certain parts of the general screen. The position and extent of the claimed area are transferred. This request can be approved or rejected, depending on whether the claimed area is available. This way it's possible for each task to always reserve the same sections for itself, since it can remember the coordinates of the first-time selection. Either by saving the Task, using nvRAM or a configuration file.
The screen is divided into 80 columns (0-79) and 25 lines (0-24). The table begins with the leftmost character on the top line.
When the Caruh system is started, Caruh reserves the first four lines (0-3) and the bottom line (24).
This is how a Task can reserve a part of the general screen:
Entry (from the Task) at address &0003
Parameter:
The number of the reserving Task is stored in TTNS3 = address &BE03
The number of MODE 2 columns is transferred in register YL
The number of lines is transferred in register YH
The command 'LD IY, &0309' would therefore display 3 rows and 9 columns
- The current table is now graphically displayed on the screen. Only every 'empty' position can be assigned. A box - consisting of lines - can now be moved using the cursor keys and pressing Copy reserves the corresponding area of the screen and enters the position in the multi-screen Table.
- If the frame can't be set at the current position, the BORDER is shown in orange color (15). Either a valid area is found or the process can be canceled using the 'ESC' key.
- The Task is finally informed whether the setting of the frame was successful.
Furthermore, X (0-79 in XL) and Y (4-23 in XH) coordinates are transferred. These correspond to the left (XL) and upper (XH) corner on the screen. Register IX contains these two values.
In addition, the corresponding screen address of the top left corner is transferred (in RAM variable C_POS).