keirf / flashfloppy-osd

On Screen Display and keyboard controller for FlashFloppy
The Unlicense
57 stars 15 forks source link

Keyboard control for Atari ST (and perhaps others) #28

Open PirxDevs opened 3 years ago

PirxDevs commented 3 years ago

I'm really missing keyboard control for Atari ST. Any chances for supporting it?

For what platforms FF OSD can potenitally support keyboard control?

keirf commented 3 years ago

Atari ST is the remaining likely one. It is harder than Amiga though. And it may require four solder points on the ST mainboard and remove a couple of resistors/links. So that OSD completely interposes on the keyboard serial protocol in both directions.

Fbeen commented 1 year ago

First off all many thanks to you Keirf for your excelent piece of work!

I want to add Atari ST keyboard as well but only one direction (rx) would be fine. I got it already working with a stm32CubeIDE code but i am not able to get USART2 or USART3 working in the FF_OSD firmware. It should be something like

#define DMA1_CH3_IRQ 13
void IRQ_13(void) __attribute__((alias("IRQ_dma1_ch3_tc")));

void atari_init(void)
{
    /* Enable RX pin (PB11) as input. */
    gpio_configure_pin(gpiob, 11, GPI_pull_up);

    /* BAUD, 8n1. */
    usart3->brr = 4608; // 36.000.000 / 7812.5
    usart3->cr1 = (USART_CR1_UE | USART_CR1_RE);
    usart2->cr3 = USART_CR3_DMAR;

    /* Initialise DMA1 channel 3 and its completion interrupt. */
    dma1->ch3.cpar = (uint32_t)(unsigned long)&usart3->dr;
    dma1->ifcr = DMA_IFCR_CGIF(3);
    IRQx_set_prio(DMA1_CH3_IRQ, 6);
    IRQx_enable(DMA1_CH3_IRQ);
}

// and the IRQ callback:

static void IRQ_dma1_ch3_tc(void)
{
    /* Clear the DMA controller. */
    dma1->ch3.ccr = 0;
    dma1->ifcr = DMA_IFCR_CGIF(3);

    printk("\nAtari key!\n");
}

Any help would be very welcome. Cheers!

keirf commented 1 year ago

You probably need to turn on the peripheral clock. Also the code you paste above references a mix of usart2 and usart3.

Fbeen commented 1 year ago

Keirf thank you for your reply. You pushed me in the right direction: i tried rcc->apb2enr |= RCC_APB1ENR_USART3EN; but it had to be rcc->apb1enr instead of rcc->apb2enr... that was why i didn´t get it work. Now i made some progress:

i added a c file "atari.c":

/*
 * atari.c
 * 
 * Inspect the Atari ST keyboard serial protocol and remember key presses.
 * 
 * Written by Frank Beentjes <frankbeen@gmail.com> & released by Keir Fraser <keir.xen@gmail.com>
 * 
 * This is free and unencumbered software released into the public domain.
 * See the file COPYING for more details, or visit <http://unlicense.org>.
 */

/* Atari keyboard:
 *  B11: Keyboard RX
 */

uint8_t stKeyboardState = 0; // keep track on the left Control and Alternate keys

void st_init(void)
{
    /* Turn on the clocks. */
    rcc->apb1enr |= RCC_APB1ENR_USART3EN;

    /* Enable RX pin (PB11) as input. */
    gpio_configure_pin(gpiob, 11, GPI_pull_up);

    /* BAUD, 8n1. */
    usart3->brr = 4608; // 36.000.000 / 7812.5
    usart3->cr1 = (USART_CR1_UE | USART_CR1_RE /* | USART_CR1_RXNEIE */ );
}

uint8_t st_check(void) 
{
    uint8_t key;

    // Check if RXNE (Read data register not empty) is set
    if(usart3->sr & USART_SR_RXNE) {

        key = usart3->dr;

    switch(key) {
    case 29: // Control pressed
        stKeyboardState |= 1 << 1;
        break;
    case 157: // Control released
        stKeyboardState &= ~(1 << 1);
        break;
    case 56: // Alternate pressed
        stKeyboardState |= 1 << 2;
        break;
    case 184: // Alternate released
        stKeyboardState &= ~(1 << 2);
        break;
    }

    // return the pressed key only when Control and Alternate are held
    if(stKeyboardState < 3) {
        return FALSE;
    }

    return key;

    }

    return FALSE;
}

and added some code to main.c:

void st_init(void);
uint8_t st_check(void);

void update_st_keys(void)
{
    uint8_t stKey;

    stKey = st_check();

    if(stKey == FALSE) {
        return;
    }

    switch(stKey) {
        // OSD Setup
        case 72: // Up
            keys |= K_SELECT;
            break;
        case 75: // Left
            keys |= K_LEFT;
            break;
        case 77: // Right
            keys |= K_RIGHT;
            break;
        case 98: // Help
            keys |= K_MENU;
            break;
        case 83: // Delete --> Set OSD on or off
            osd_on ^= 1;
            snprintf((char *)notify.text[0], sizeof(notify.text[0]),
                 "OSD O%s", osd_on ? "n" : "ff");
            notify.cols = strlen((char *)notify.text[0]);
            notify.rows = 1;
            notify.on = TRUE;
            notify_time = time_now();
            break;
    }
}

And finaly in the main fuction called st_init() once and in the main loop after update_amiga_keys() calling update_st_keys()