Compare commits

..

10 commits

Author SHA1 Message Date
Peter Weingartner 21fe8ef908 Added timeout to PS/2 keyboard init 2025-01-08 20:41:58 -05:00
Peter Weingartner 7641982319 Corrections for interrupt race condition 2025-01-05 20:48:50 -05:00
Peter Weingartner 97cedc8659 Added code to initialize PS/2 keyboards 2025-01-05 20:24:24 -05:00
pweingar dbe1fd298b
Merge pull request #3 from pweingar/fast-scroll
Fast scroll
2025-01-04 15:27:42 -05:00
pweingar 9b7dab7c2a
Merge branch 'main' into fast-scroll 2025-01-04 15:27:31 -05:00
Peter Weingartner 5279776737 Exposed F256 BREAK key to IOCTRL 2024-12-26 18:40:07 -05:00
Peter Weingartner 83d3c74839 Window scrolling speed up
Tweaked the case where we are scrolling only part of the window to use MVN/MVP to move lines.
2024-12-24 22:27:11 -05:00
Peter Weingartner 275e0d7ec8 Basic scroll case speed-up 2024-12-24 19:58:13 -05:00
Peter Weingartner 9dacef1f57 Logging reduced and redirected
Moved logging up to ERROR level and moved it off the UART to avoid possibly clobbering user programs needing the serial port.
2024-12-22 22:33:11 -05:00
Peter Weingartner 206f2d5e6b Fixed SDC sector count logic for SDC read/write 2024-12-22 21:21:47 -05:00
88 changed files with 4215 additions and 4074 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -1,7 +1,10 @@
.public restart_cli .public restart_cli
.public io_copy_down
.public io_copy_up
.extern proc_shell_address .extern proc_shell_address
.extern _Vfp .extern _Vfp
.extern _Dp
.extern _DirectPageStart .extern _DirectPageStart
#ifndef __CALYPSI_DATA_MODEL_SMALL__ #ifndef __CALYPSI_DATA_MODEL_SMALL__
@ -11,6 +14,42 @@
.section stack .section stack
.section farcode .section farcode
;
; void io_copy_down(uint16_t count, uint16_t dest, uint16_t src)
;
io_copy_down: pha
phx
phy
phb
ldy dp:.tiny (_Dp)
ldx dp:.tiny (_Dp+4)
mvn #0xf0, #0xf0
plb
ply
plx
pla
rtl
;
; void io_copy_up(uint16_t count, uint16_t dest, uint16_t src)
;
io_copy_up: pha
phx
phy
phb
ldy dp:.tiny (_Dp)
ldx dp:.tiny (_Dp+4)
mvp #0xf0, #0xf0
plb
ply
plx
pla
rtl
; ;
; Reset the stack to the initial value. ; Reset the stack to the initial value.
; Reset the direct page and data bank registers ; Reset the direct page and data bank registers

View file

@ -7,11 +7,8 @@
*/ */
#include "log_level.h" #include "log_level.h"
#ifdef DEFAULT_LOG_LEVEL
//#undef DEFAULT_LOG_LEVEL
#endif
#ifndef DEFAULT_LOG_LEVEL #ifndef DEFAULT_LOG_LEVEL
#define DEFAULT_LOG_LEVEL LOG_TRACE #define DEFAULT_LOG_LEVEL LOG_ERROR
#endif #endif
#include <string.h> #include <string.h>

View file

@ -762,6 +762,8 @@ short con_ioctrl(p_channel chan, short command, uint8_t * buffer, short size) {
/* Return the result of the BREAK key test */ /* Return the result of the BREAK key test */
#if MODEL == MODEL_FOENIX_A2560K #if MODEL == MODEL_FOENIX_A2560K
return kbdmo_break(); return kbdmo_break();
#elif MODEL == MODEL_FOENIX_F256 || MODEL == MODEL_FOENIX_F256K || MODEL == MODEL_FOENIX_F256K2 || MODEL == MODEL_FOENIX_F256JR2
return kbd_break();
#else #else
/* TODO: flesh this out for the A2560U */ /* TODO: flesh this out for the A2560U */
return 0; return 0;

View file

@ -492,19 +492,12 @@ SYSTEMCALL void int_clear(unsigned short n) {
void int_handle_irq() { void int_handle_irq() {
uint8_t mask_bits = 0; uint8_t mask_bits = 0;
// vky_text_matrix[0] += 1;
// if (*irq_ram_vector != 0) {
// p_int_handler handler = (p_int_handler)(*irq_ram_vector);
// handler();
// return;
// }
// vky_text_matrix[1] += 1;
// Process any pending interrupts in group 0 // Process any pending interrupts in group 0
mask_bits = *PENDING_GRP0; mask_bits = *PENDING_GRP0;
if (mask_bits) { if (mask_bits) {
// Clear the pending bits for group 0
*PENDING_GRP0 = mask_bits;
if ((mask_bits & 0x01) && int_handle_00) int_handle_00(); // Start of frame if ((mask_bits & 0x01) && int_handle_00) int_handle_00(); // Start of frame
if ((mask_bits & 0x02) && int_handle_01) int_handle_01(); // Start of line if ((mask_bits & 0x02) && int_handle_01) int_handle_01(); // Start of line
if ((mask_bits & 0x04) && int_handle_02) int_handle_02(); // PS/2 Keyboard if ((mask_bits & 0x04) && int_handle_02) int_handle_02(); // PS/2 Keyboard
@ -513,42 +506,31 @@ void int_handle_irq() {
if ((mask_bits & 0x20) && int_handle_05) int_handle_05(); // Timer 1 if ((mask_bits & 0x20) && int_handle_05) int_handle_05(); // Timer 1
if ((mask_bits & 0x40) && int_handle_06) int_handle_06(); // Reserved if ((mask_bits & 0x40) && int_handle_06) int_handle_06(); // Reserved
if ((mask_bits & 0x80) && int_handle_07) int_handle_07(); // Cartridge if ((mask_bits & 0x80) && int_handle_07) int_handle_07(); // Cartridge
// Clear the pending bits for group 0
*PENDING_GRP0 = mask_bits;
} }
// Process any pending interrupts in group 1 // Process any pending interrupts in group 1
mask_bits = *PENDING_GRP1; mask_bits = *PENDING_GRP1;
if (mask_bits) { if (mask_bits) {
volatile __attribute__((far)) char * text = (char *)0xafa000; // Clear the pending bits for group 1
*text = *text + 1; *PENDING_GRP1 = mask_bits;
if ((mask_bits & 0x01) && int_handle_10) { if ((mask_bits & 0x01) && int_handle_10) int_handle_10(); // UART
volatile __attribute__((far)) char * text = (char *)0xafa001;
*text = *text + 1;
int_handle_10(); // PS/2 Keyboard
}
if ((mask_bits & 0x00) && int_handle_10) int_handle_10(); // UART
if ((mask_bits & 0x10) && int_handle_14) int_handle_14(); // RTC if ((mask_bits & 0x10) && int_handle_14) int_handle_14(); // RTC
if ((mask_bits & 0x20) && int_handle_15) int_handle_15(); // VIA if ((mask_bits & 0x20) && int_handle_15) int_handle_15(); // VIA
if ((mask_bits & 0x40) && int_handle_16) int_handle_16(); // F256K Matrix Keyboard if ((mask_bits & 0x40) && int_handle_16) int_handle_16(); // F256K Matrix Keyboard
if ((mask_bits & 0x80) && int_handle_17) int_handle_17(); // SD card inserted if ((mask_bits & 0x80) && int_handle_17) int_handle_17(); // SD card inserted
// Clear the pending bits for group 1
*PENDING_GRP1 = mask_bits;
} }
// Process any pending interrupts in group 2 // Process any pending interrupts in group 2
mask_bits = *PENDING_GRP2; mask_bits = *PENDING_GRP2;
if (mask_bits) { if (mask_bits) {
if ((mask_bits & 0x01) && int_handle_20) int_handle_20(); // IED Data IN
if ((mask_bits & 0x02) && int_handle_21) int_handle_21(); // IED Clock IN
if ((mask_bits & 0x02) && int_handle_22) int_handle_22(); // IED ATN IN
if ((mask_bits & 0x02) && int_handle_22) int_handle_23(); // IED SREQ IN
// Clear the pending bits for group 2 // Clear the pending bits for group 2
*PENDING_GRP2 = mask_bits; *PENDING_GRP2 = mask_bits;
if ((mask_bits & 0x01) && int_handle_20) int_handle_20(); // IED Data IN
if ((mask_bits & 0x02) && int_handle_21) int_handle_21(); // IED Clock IN
if ((mask_bits & 0x04) && int_handle_22) int_handle_22(); // IED ATN IN
if ((mask_bits & 0x08) && int_handle_22) int_handle_23(); // IED SREQ IN
} }
} }

View file

@ -19,16 +19,21 @@
#include <stdbool.h> #include <stdbool.h>
#include "errors.h"
#include "interrupt.h" #include "interrupt.h"
#include "log.h" #include "log.h"
#include "ps2_reg.h" #include "ps2_reg.h"
#include "ring_buffer.h" #include "ring_buffer.h"
#include "sys_macros.h" #include "sys_macros.h"
#include "timers.h"
// //
// Constants // Constants
// //
#define KBD_TIMEOUT (60 * 5)
#define KBD_RETRIES 10
/* /*
* Modifier bit flags * Modifier bit flags
*/ */
@ -143,17 +148,33 @@ static bool break_pressed = false;
// Code // Code
// //
static void kbd_send_cmd(uint8_t byte) { /**
* Clear out the FIFO for the keyboard
*/
static void kbd_clear_fifo() {
*PS2_CTRL |= PS2_CTRL_KBD_CLR;
*PS2_CTRL &= ~PS2_CTRL_KBD_CLR;
}
static short kbd_send_cmd(uint8_t byte) {
uint8_t status = 0; uint8_t status = 0;
*PS2_OUT = byte; *PS2_OUT = byte;
*PS2_CTRL |= PS2_CTRL_KBD_WR; *PS2_CTRL |= PS2_CTRL_KBD_WR;
long timeout = timers_jiffies() + KBD_TIMEOUT;
do { do {
if (timeout < timers_jiffies()) {
*PS2_CTRL &= ~PS2_CTRL_KBD_WR;
return DEV_TIMEOUT;
}
status = *PS2_STAT; status = *PS2_STAT;
} while ((status & (PS2_STAT_KBD_ACK | PS2_STAT_KBD_NAK)) == 0); } while ((status & (PS2_STAT_KBD_ACK | PS2_STAT_KBD_NAK)) == 0);
*PS2_CTRL &= ~PS2_CTRL_KBD_WR; *PS2_CTRL &= ~PS2_CTRL_KBD_WR;
return 0;
} }
/** /**
@ -406,7 +427,7 @@ static void kbd_process_set2_bytecode(uint8_t byte_code) {
*/ */
SYSTEMCALL void kbd_handle_irq() { SYSTEMCALL void kbd_handle_irq() {
// Check to see if there is a keyboard bytecode waiting... process it if so // Check to see if there is a keyboard bytecode waiting... process it if so
if ((*PS2_STAT & PS2_STAT_KBD_EMP) == 0) { while ((*PS2_STAT & PS2_STAT_KBD_EMP) == 0) {
kbd_process_set2_bytecode(*PS2_KBD_IN); kbd_process_set2_bytecode(*PS2_KBD_IN);
} }
} }
@ -445,6 +466,11 @@ bool kbd_break() {
* *
*/ */
short kbd_sc_init() { short kbd_sc_init() {
short result = 0;
// Make sure the keyboard interrupt is disabled
int_disable(INT_KBD_PS2);
// Initialize the keyboard buffers // Initialize the keyboard buffers
rb_word_init(&scan_code_buffer); rb_word_init(&scan_code_buffer);
rb_word_init(&char_buffer); rb_word_init(&char_buffer);
@ -454,11 +480,50 @@ short kbd_sc_init() {
modifiers = 0; modifiers = 0;
break_pressed = false; break_pressed = false;
// Reset the keyboard
result = kbd_send_cmd(0xff);
if (result < 0) {
INFO1("PS/2: unable to reset the keyboard: %s", err_message(ressult));
return result;
}
INFO("kbd_sc_init: ps/2 keyboard reset");
kbd_clear_fifo();
// Disable scanning
result = kbd_send_cmd(0xf5);
if (result < 0) {
INFO1("PS/2: unable to disable keyboard scanning: %s", err_message(ressult));
return result;
}
INFO("kbd_sc_init: ps/2 scanning disabled");
// Set scan code set #2
result = kbd_send_cmd(0xf0);
if (result < 0) {
INFO1("PS/2: unable to set scan code: %s", err_message(ressult));
return result;
}
result = kbd_send_cmd(0x02);
if (result < 0) {
INFO1("PS/2: unable to send scan code set: %s", err_message(ressult));
return result;
}
INFO("kbd_sc_init: ps/2 scan code set #2 selected");
// Enable scanning
result = kbd_send_cmd(0xf4);
if (result < 0) {
INFO1("PS/2: unable to restart keyboard scanning: %s", err_message(ressult));
return result;
}
INFO("kbd_sc_init: ps/2 scanning enabled");
// Register and enable the PS/2 interrupt handler // Register and enable the PS/2 interrupt handler
int_register(INT_KBD_PS2, (p_int_handler)kbd_handle_irq); int_register(INT_KBD_PS2, (p_int_handler)kbd_handle_irq);
int_enable(INT_KBD_PS2); int_enable(INT_KBD_PS2);
return 0; return result;
} }
#endif #endif

View file

@ -23,6 +23,7 @@
#include "interrupt.h" #include "interrupt.h"
#include "F256/sdc_spi.h" #include "F256/sdc_spi.h"
#include "sdc_f256.h" #include "sdc_f256.h"
#include "utilities.h"
/* MMC/SD command (SPI mode) */ /* MMC/SD command (SPI mode) */
#define CMD0 (0) /* GO_IDLE_STATE */ #define CMD0 (0) /* GO_IDLE_STATE */
@ -379,7 +380,7 @@ static short sdc_read(p_dev_block dev, long lba, uint8_t * buffer, short size) {
p_sd_card_info card = (p_sd_card_info)dev->data; p_sd_card_info card = (p_sd_card_info)dev->data;
p_sdc_spi sd = card->reg; p_sdc_spi sd = card->reg;
uint8_t cmd; uint8_t cmd;
short count = size % 512 + 1; short count = ceil_div_short(size, 512);
if (card->status & SDC_STAT_NOINIT) { if (card->status & SDC_STAT_NOINIT) {
return ERR_NOT_READY; return ERR_NOT_READY;
@ -420,7 +421,7 @@ static short sdc_write(p_dev_block dev, long lba, const uint8_t * buffer, short
p_sd_card_info card = (p_sd_card_info)dev->data; p_sd_card_info card = (p_sd_card_info)dev->data;
p_sdc_spi sd = card->reg; p_sdc_spi sd = card->reg;
uint8_t cmd; uint8_t cmd;
short count = size % 512 + 1; short count = ceil_div_short(size, 512);
if (card->status & SDC_STAT_NOINIT) { if (card->status & SDC_STAT_NOINIT) {
return ERR_NOT_READY; return ERR_NOT_READY;

View file

@ -406,14 +406,59 @@ static short txt_f256_set_color(unsigned char foreground, unsigned char backgrou
return 0; return 0;
} }
extern void io_copy_down(uint16_t count, uint16_t dest, uint16_t src);
extern void io_copy_up(uint16_t count, uint16_t dest, uint16_t src);
/**
* Copy data in the I/O space using the MVN/MVP instructions
*
* @param count the number of bytes to copy
* @param dest the address within the I/O bank to copy to
* @param src the address within the I/O bank to copy from
*/
static void io_copy(uint16_t count, uint16_t dest, uint16_t src) {
if (dest < src) {
io_copy_down(count, dest, src);
} else {
io_copy_up(count, dest, src);
}
}
/**
* Scroll the screen for the most common case: full screen scrolls up by one full row.
*/
static void txt_f256_scroll_simple() {
uint16_t rows = f256_max_size.height;
uint16_t columns = f256_max_size.width;
uint16_t count = (rows - 1) * columns;
// Move the rows up
uint16_t text_dest = (uint16_t)((uint32_t)tvky_text_matrix & 0xffff);
uint16_t text_src = text_dest + columns;
io_copy_down(count, text_dest, text_src);
uint16_t color_dest = (uint16_t)((uint32_t)tvky_color_matrix & 0xffff);
uint16_t color_src = color_dest + columns;
io_copy_down(count, color_dest, color_src);
// Clear the bottom line
for (uint16_t i = count; i < rows * columns; i++) {
tvky_text_matrix[i] = ' ';
tvky_color_matrix[i] = f256_color;
}
}
/** /**
* Scroll the text in the current region * Scroll the text in the current region
* *
* Supports the general case
*
* @param screen the number of the text device * @param screen the number of the text device
* @param horizontal the number of columns to scroll (negative is left, positive is right) * @param horizontal the number of columns to scroll (negative is left, positive is right)
* @param vertical the number of rows to scroll (negative is down, positive is up) * @param vertical the number of rows to scroll (negative is down, positive is up)
*/ */
static void txt_f256_scroll(short horizontal, short vertical) { static void txt_f256_scroll_complex(short horizontal, short vertical) {
short x, x0, x1, x2, x3, dx; short x, x0, x1, x2, x3, dx;
short y, y0, y1, y2, y3, dy; short y, y0, y1, y2, y3, dy;
@ -468,12 +513,24 @@ static void txt_f256_scroll(short horizontal, short vertical) {
row_src += delta_y; row_src += delta_y;
int offset_dst = row_dst + x0 - dx; int offset_dst = row_dst + x0 - dx;
int offset_src = row_src + horizontal + x0 - dx; int offset_src = row_src + horizontal + x0 - dx;
for (x = x0; x != x2; x += dx) {
offset_dst += dx; // Move the rows up
offset_src += dx; uint16_t count = x2 - x0;
tvky_text_matrix[offset_dst] = tvky_text_matrix[offset_src];
tvky_color_matrix[offset_dst] = tvky_color_matrix[offset_src]; uint16_t text_dest = (uint16_t)((uint32_t)tvky_text_matrix & 0xffff) + offset_dst;
} uint16_t text_src = (uint16_t)((uint32_t)tvky_text_matrix & 0xffff) + offset_src;
io_copy(count, text_dest, text_src);
uint16_t color_dest = (uint16_t)((uint32_t)tvky_color_matrix & 0xffff) + offset_dst;
uint16_t color_src = (uint16_t)((uint32_t)tvky_color_matrix & 0xffff) + offset_src;
io_copy(count, color_dest, color_src);
// for (x = x0; x != x2; x += dx) {
// offset_dst += dx;
// offset_src += dx;
// tvky_text_matrix[offset_dst] = tvky_text_matrix[offset_src];
// tvky_color_matrix[offset_dst] = tvky_color_matrix[offset_src];
// }
} }
/* Clear the rectangles */ /* Clear the rectangles */
@ -499,6 +556,22 @@ static void txt_f256_scroll(short horizontal, short vertical) {
} }
} }
} }
/**
* Scroll the text in the current region
*
* @param horizontal the number of columns to scroll (negative is left, positive is right)
* @param vertical the number of rows to scroll (negative is down, positive is up)
*/
static void txt_f256_scroll(short horizontal, short vertical) {
// If we're scrolling up one, and the region is the full screen, use a faster scrolling routine
if ((horizontal == 0) && (vertical == 1) &&
(f256_region.origin.x == 0) && (f256_region.origin.y == 0) &&
(f256_region.size.width == f256_max_size.width) && (f256_region.size.height == f256_max_size.height)) {
txt_f256_scroll_simple();
} else {
txt_f256_scroll_complex(horizontal, vertical);
}
}
/** /**
* Fill the current region with a character in the current color * Fill the current region with a character in the current color

View file

@ -3,8 +3,8 @@
*/ */
#include "log_level.h" #include "log_level.h"
#define DEFAULT_LOG_LEVEL LOG_INFO #define DEFAULT_LOG_LEVEL LOG_ERROR
#define LOG_CHANNEL LOG_CHANNEL_UART0 #define LOG_CHANNEL LOG_CHANNEL_CHANNEL_A
#include <ctype.h> #include <ctype.h>
#include <stdio.h> #include <stdio.h>

View file

@ -7,6 +7,16 @@
#include <ctype.h> #include <ctype.h>
#include "utilities.h" #include "utilities.h"
/**
* Return the ceiling of a/b using only short operations
*
* @param a the numerator
* @param b the denominator
* @return the smallest short c such that c >= a / b
*/
short ceil_div_short(short a, short b) {
return (a + (b - 1)) / b;
}
/** /**
* Re-entrant version of strtok_r, because VBCC does not provide it * Re-entrant version of strtok_r, because VBCC does not provide it

View file

@ -13,6 +13,15 @@
/** Return the maximum value of x or y */ /** Return the maximum value of x or y */
#define max(x, y) ((x < y) ? y : x) #define max(x, y) ((x < y) ? y : x)
/**
* Return the ceiling of a/b using only short operations
*
* @param a the numerator
* @param b the denominator
* @return the smallest short c such that c >= a / b
*/
extern short ceil_div_short(short a, short b);
/** /**
* Re-entrant version of strtok_r, because VBCC does not provide it * Re-entrant version of strtok_r, because VBCC does not provide it
* *

View file

@ -7,6 +7,6 @@
#define VER_MAJOR 1 #define VER_MAJOR 1
#define VER_MINOR 1 #define VER_MINOR 1
#define VER_BUILD 9 #define VER_BUILD 29
#endif #endif