Skip to content

Commit

Permalink
Added C64 keyboard simulator part and added some initial mapping.
Browse files Browse the repository at this point in the history
  • Loading branch information
patrikaxelsson committed Aug 12, 2016
1 parent a31093d commit ad7e653
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 33 deletions.
20 changes: 20 additions & 0 deletions amiga_keyb_codes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef __AMIGA_KEYB_CODES_H__
#define __AMIGA_KEYB_CODES_H__

enum AmigaKey {
AmigaKey_A = 0x20,
AmigaKey_B = 0x35,
AmigaKey_P = 0x19,
AmigaKey_Space = 0x40,
AmigaKey_Return = 0x44,

//Special
AmigaKey_ResetWarning = 0x78,
AmigaKey_LastKeyCodeBad = 0xf9,
AmigaKey_OutputBufferOverflow = 0xfa,
AmigaKey_SelftestFailed = 0xfc,
AmigaKey_InitiatePowerUpStream = 0xfd,
AmigaKey_TerminatePowerUpStream = 0xfe,
};

#endif
58 changes: 58 additions & 0 deletions amiga_keyb_if.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdbool.h>

#define KEYB_IN PIND
#define KEYB_OUT PORTD
#define KEYB_DDR DDRD
#define KEYB_CLK PIND2
#define KEYB_DAT PIND3
#define KEYB_MASK (_BV(KEYB_DAT) | _BV(KEYB_CLK))

static volatile uint8_t keyboardData = 0xff;
static void (*changeCallback)(uint8_t, bool) = 0;

ISR (PCINT3_vect) {
static uint8_t tmpData = 0x00;
static uint8_t bitPos = 6;

if (bit_is_clear(KEYB_IN, KEYB_CLK)) {
tmpData |= ((bit_is_clear(KEYB_IN, KEYB_DAT) ? 1 : 0) << bitPos);
if(7 == bitPos) {
keyboardData = tmpData;
if(0 != changeCallback) {
changeCallback(tmpData & 0x7f, tmpData & 0x80);
}
tmpData = 0x00;
}
bitPos--;
bitPos &= 7; // Wrap -> 7
}
else {
if (6 == bitPos) {
KEYB_OUT &= ~_BV(KEYB_DAT); // Disable pull-up and set to zero/low if used for output
KEYB_DDR |= _BV(KEYB_DAT); // Set to output
_delay_us(85);
KEYB_DDR &= ~_BV(KEYB_DAT); // Set to input
KEYB_OUT |= _BV(KEYB_DAT); // Enable pull-up
}
}
}

void amiga_keyb_if_init() {
KEYB_DDR &= ~KEYB_MASK;
KEYB_OUT |= KEYB_MASK; //Pullup

PCICR |= _BV(PCIE3);
PCMSK3 |= _BV(PCINT26);
sei();
}

uint8_t amiga_keyb_if_getKey() {
return keyboardData;
}

void amiga_keyb_if_registerChangeCallback(void (*newChangeCallback)(uint8_t, bool)) {
changeCallback = newChangeCallback;
}
8 changes: 8 additions & 0 deletions amiga_keyb_if.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef __AMIGA_KEYB_IF_H__
#define __AMIGA_KEYB_IF_H__

void amiga_keyb_if_init();
uint8_t amiga_keyb_if_getKey();
void amiga_keyb_if_registerChangeCallback(void (*)(uint8_t, bool));

#endif
12 changes: 12 additions & 0 deletions c64_keyb_codes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef __C64_KEYB_CODES_H__
#define __C64_KEYB_CODES_H__

enum C64Key {
C64Key_A = 0x12,
C64Key_B = 0x34,
C64Key_P = 0x51,
C64Key_Space = 0x74,
C64Key_Return = 0x01,
};

#endif
45 changes: 45 additions & 0 deletions c64_keyb_sim.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>

#define KEYB_COLS_IN PINA
#define KEYB_COLS_OUT PINA
#define KEYB_COLS_DDR DDRA
#define KEYB_ROWS_IN PINC
#define KEYB_ROWS_OUT PORTC
#define KEYB_ROWS_DDR DDRC

static uint8_t rowState[256] = {0};

ISR (PCINT0_vect) {
KEYB_ROWS_DDR = rowState[KEYB_COLS_IN];
}

void c64_keyb_sim_init() {
KEYB_COLS_DDR = 0x00; //Input
KEYB_COLS_OUT = 0xff; //Pullup

KEYB_ROWS_DDR = 0x00; //Input
KEYB_ROWS_OUT = 0x00; //Output zero whenever set to output

PCICR |= _BV(PCIE0);
PCMSK0 = 0xff; // Generate input on all COLS
sei();
}

void c64_keyb_sim_setKey(uint8_t c64Key, bool up) {
const uint8_t column = c64Key >> 4;
const uint8_t rowData = 1 << (c64Key & 0x7);
uint16_t i;

for(i = 0; i < 256; i++) {
if(i & (1 << column)) {
if(up) {
rowState[(uint8_t)~i] &= ~rowData;
}
else {
rowState[(uint8_t)~i] |= rowData;
}
}
}
}
7 changes: 7 additions & 0 deletions c64_keyb_sim.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef __C64_KEYBOARD_SIMULATOR__
#define __C64_KEYBOARD_SIMULATOR__

void c64_keyb_sim_init();
void c64_keyb_sim_setKey(uint8_t c64Key, bool up);

#endif
60 changes: 27 additions & 33 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,47 @@
#include <stdio.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdbool.h>

#include "amiga_keyboard.h"
#include "amiga_keyb_if.h"
#include "c64_keyb_sim.h"
#include "amiga_keyb_codes.h"
#include "c64_keyb_codes.h"

#define BAUD 9600
#include <util/setbaud.h>
#include "uart.h"

void uart_init(void) {
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
void updateC64KeyState(uint8_t amigaKey, bool up) {
switch(amigaKey) {
case AmigaKey_A: c64_keyb_sim_setKey(C64Key_A, up); break;
case AmigaKey_B: c64_keyb_sim_setKey(C64Key_B, up); break;
case AmigaKey_P: c64_keyb_sim_setKey(C64Key_P, up); break;

#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif

UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */
}

int uart_putchar(char c, FILE *stream) {
if (c == '\n') {
uart_putchar('\r', stream);
}
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = c;
return 0;
case AmigaKey_Space: c64_keyb_sim_setKey(C64Key_Space, up); break;
case AmigaKey_Return: c64_keyb_sim_setKey(C64Key_Return, up); break;
}
}

FILE uart_output = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);

int main(void) {
MCUCR |= _BV(JTD);
MCUCR |= _BV(JTD);
uart_init();
FILE uart_output = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
stdout = &uart_output;

amiga_keyboard_init();
amiga_keyb_if_init();
amiga_keyb_if_registerChangeCallback(&updateC64KeyState);

puts("starting!!!");

uint8_t prevKey = amiga_keyboard_getkey();
for(;;) {
uint8_t key = amiga_keyboard_getkey();

if (key != prevKey)
printf("%02x\n", key);
c64_keyb_sim_init();

prevKey = key;
uint8_t prevAmigaKey = amiga_keyb_if_getKey();
for(;;) {
const uint8_t amigaKey = amiga_keyb_if_getKey();
if (amigaKey != prevAmigaKey) {
printf("%02x\n", amigaKey);
}
prevAmigaKey = amigaKey;
}

return 0;
Expand Down
28 changes: 28 additions & 0 deletions uart.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <avr/io.h>
#include <stdio.h>
#define BAUD 115200
#include <util/setbaud.h>

void uart_init(void) {
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;

#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~(_BV(U2X0));
#endif

UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */
}

int uart_putchar(char c, FILE *stream) {
if (c == '\n') {
uart_putchar('\r', stream);
}
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = c;
return 0;
}

7 changes: 7 additions & 0 deletions uart.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#ifndef __UART_H__
#define __UART_H__

void uart_init(void);
int uart_putchar(char c, FILE *stream);

#endif

0 comments on commit ad7e653

Please sign in to comment.