mirror of
https://github.com/LIV2/amiga-par-to-spi-adapter.git
synced 2025-12-05 22:22:44 +00:00
Add support for RP2040 microcontroller
This commit is contained in:
parent
30736877bd
commit
e377afae11
15
rp2040/CMakeLists.txt
Normal file
15
rp2040/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
include(pico_sdk_import.cmake)
|
||||
|
||||
project(par_spi C CXX ASM)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
pico_sdk_init()
|
||||
|
||||
add_executable(par_spi par_spi.c)
|
||||
|
||||
pico_add_extra_outputs(par_spi)
|
||||
|
||||
target_link_libraries(par_spi pico_stdlib hardware_spi)
|
||||
19
rp2040/README.md
Normal file
19
rp2040/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
# RP2040 version
|
||||
|
||||
The code for the AVR microcontroller has been ported to the RP2040 microcontroller.
|
||||
RP2040 is the microcontroller used on the Raspberry Pi Pico board.
|
||||
|
||||
## Build instructions
|
||||
|
||||
The [Raspberry Pi Pico SDK](https://github.com/raspberrypi/pico-sdk) must be installed.
|
||||
Then, standing in the rp2040 subdirectory, execute:
|
||||
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
export PICO_SDK_PATH=~/pico/pico-sdk
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
|
||||
Copy the generated file `build/par_spi.uf2` to the microcontroller's flash.
|
||||
206
rp2040/par_spi.c
Normal file
206
rp2040/par_spi.c
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Written in October 2022 by Niklas Ekström.
|
||||
*
|
||||
* Runs on RP2040 microcontroller instead of AVR as before,
|
||||
* but uses the same protocol and Amiga software.
|
||||
*/
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/spi.h"
|
||||
|
||||
// Pin name GPIO Direction Comment Description
|
||||
#define PIN_D(x) (0+x) // In/out
|
||||
#define PIN_IRQ 8 // Output Active low
|
||||
#define PIN_ACT 9 // Output Active low
|
||||
#define PIN_CLK 10 // Input
|
||||
#define PIN_REQ 11 // Input Active low
|
||||
#define PIN_MISO 16 // Input Pull-up
|
||||
#define PIN_SS 17 // Output Active low
|
||||
#define PIN_SCK 18 // Output
|
||||
#define PIN_MOSI 19 // Output
|
||||
#define PIN_CDET 20 // Input Pull-up Card Detect
|
||||
|
||||
#define SPI_SLOW_FREQUENCY (400*1000)
|
||||
#define SPI_FAST_FREQUENCY (16*1000*1000)
|
||||
|
||||
static uint32_t prev_cdet;
|
||||
|
||||
static void handle_request() {
|
||||
uint32_t pins;
|
||||
|
||||
while (1) {
|
||||
pins = gpio_get_all();
|
||||
if (!(pins & (1 << PIN_REQ)))
|
||||
break;
|
||||
|
||||
if ((pins & (1 << PIN_CDET)) != prev_cdet) {
|
||||
gpio_put(PIN_IRQ, false);
|
||||
gpio_set_dir(PIN_IRQ, true);
|
||||
prev_cdet = pins & (1 << PIN_CDET);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t prev_clk = pins & (1 << PIN_CLK);
|
||||
|
||||
if ((pins & 0xc0) != 0xc0) {
|
||||
uint32_t byte_count = 0;
|
||||
bool read = false;
|
||||
|
||||
if (!(pins & 0x80)) { // READ1 or WRITE1
|
||||
read = !!(pins & 0x40);
|
||||
byte_count = pins & 0x3f;
|
||||
|
||||
gpio_put(PIN_ACT, 0);
|
||||
} else { // READ2 or WRITE2
|
||||
byte_count = (pins & 0x3f) << 7;
|
||||
|
||||
gpio_put(PIN_ACT, 0);
|
||||
|
||||
while (1) {
|
||||
pins = gpio_get_all();
|
||||
if ((pins & (1 << PIN_CLK)) != prev_clk)
|
||||
break;
|
||||
|
||||
if (pins & (1 << PIN_REQ))
|
||||
return;
|
||||
}
|
||||
|
||||
read = !!(pins & 0x80);
|
||||
byte_count |= pins & 0x7f;
|
||||
prev_clk = pins & (1 << PIN_CLK);
|
||||
}
|
||||
|
||||
if (read) {
|
||||
spi_get_hw(spi0)->dr = 0xff;
|
||||
|
||||
uint32_t prev_ss = pins & (1 << PIN_SS);
|
||||
|
||||
while (1) {
|
||||
while (!spi_is_readable(spi0))
|
||||
tight_loop_contents();
|
||||
|
||||
uint32_t value = spi_get_hw(spi0)->dr;
|
||||
|
||||
while (1) {
|
||||
pins = gpio_get_all();
|
||||
if ((pins & (1 << PIN_CLK)) != prev_clk)
|
||||
break;
|
||||
|
||||
if (pins & (1 << PIN_REQ))
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_put_all(prev_ss | value);
|
||||
gpio_set_dir_out_masked(0xff);
|
||||
|
||||
if (!byte_count)
|
||||
break;
|
||||
|
||||
spi_get_hw(spi0)->dr = 0xff;
|
||||
prev_clk = pins & (1 << PIN_CLK);
|
||||
byte_count--;
|
||||
}
|
||||
} else {
|
||||
while (1) {
|
||||
while (1) {
|
||||
pins = gpio_get_all();
|
||||
if ((pins & (1 << PIN_CLK)) != prev_clk)
|
||||
break;
|
||||
|
||||
if (pins & (1 << PIN_REQ))
|
||||
return;
|
||||
}
|
||||
|
||||
spi_get_hw(spi0)->dr = pins & 0xff;
|
||||
|
||||
while (!spi_is_readable(spi0))
|
||||
tight_loop_contents();
|
||||
|
||||
(void)spi_get_hw(spi0)->dr;
|
||||
|
||||
if (!byte_count)
|
||||
break;
|
||||
|
||||
prev_clk = pins & (1 << PIN_CLK);
|
||||
byte_count--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch ((pins & 0x3e) >> 1) {
|
||||
case 0: { // SPI_SELECT
|
||||
gpio_put(PIN_SS, !(pins & 1));
|
||||
gpio_put(PIN_ACT, 0);
|
||||
break;
|
||||
}
|
||||
case 1: { // CARD_PRESENT
|
||||
gpio_set_dir(PIN_IRQ, false);
|
||||
gpio_put(PIN_ACT, 0);
|
||||
|
||||
while (1) {
|
||||
pins = gpio_get_all();
|
||||
if ((pins & (1 << PIN_CLK)) != prev_clk)
|
||||
break;
|
||||
|
||||
if (pins & (1 << PIN_REQ))
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_put(PIN_D(0), !gpio_get(PIN_CDET));
|
||||
gpio_set_dir_out_masked(0xff);
|
||||
break;
|
||||
}
|
||||
case 2: { // SPEED
|
||||
spi_set_baudrate(spi0, pins & 1 ?
|
||||
SPI_FAST_FREQUENCY :
|
||||
SPI_SLOW_FREQUENCY);
|
||||
|
||||
gpio_put(PIN_ACT, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
pins = gpio_get_all();
|
||||
if (pins & (1 << PIN_REQ))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
spi_init(spi0, SPI_SLOW_FREQUENCY);
|
||||
|
||||
gpio_set_function(PIN_SCK, GPIO_FUNC_SPI);
|
||||
gpio_set_function(PIN_MOSI, GPIO_FUNC_SPI);
|
||||
gpio_set_function(PIN_MISO, GPIO_FUNC_SPI);
|
||||
gpio_pull_up(PIN_MISO);
|
||||
|
||||
gpio_init(PIN_SS);
|
||||
gpio_put(PIN_SS, 1);
|
||||
gpio_set_dir(PIN_SS, GPIO_OUT);
|
||||
|
||||
gpio_init(PIN_CDET);
|
||||
gpio_pull_up(PIN_CDET);
|
||||
|
||||
for (int i = 0; i < 12; i++)
|
||||
gpio_init(i);
|
||||
|
||||
gpio_put(PIN_ACT, 1);
|
||||
gpio_set_dir(PIN_ACT, GPIO_OUT);
|
||||
|
||||
prev_cdet = gpio_get_all() & (1 << PIN_CDET);
|
||||
|
||||
while (1) {
|
||||
handle_request();
|
||||
|
||||
gpio_set_dir_in_masked(0xff);
|
||||
gpio_clr_mask(0xff);
|
||||
|
||||
gpio_put(PIN_ACT, 1);
|
||||
|
||||
while (spi_is_busy(spi0))
|
||||
tight_loop_contents();
|
||||
|
||||
if (spi_is_readable(spi0))
|
||||
(void)spi_get_hw(spi0)->dr;
|
||||
}
|
||||
}
|
||||
73
rp2040/pico_sdk_import.cmake
Normal file
73
rp2040/pico_sdk_import.cmake
Normal file
@ -0,0 +1,73 @@
|
||||
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
|
||||
|
||||
# This can be dropped into an external project to help locate this SDK
|
||||
# It should be include()ed prior to project()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
|
||||
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
|
||||
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
|
||||
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
|
||||
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
|
||||
|
||||
if (NOT PICO_SDK_PATH)
|
||||
if (PICO_SDK_FETCH_FROM_GIT)
|
||||
include(FetchContent)
|
||||
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
|
||||
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
||||
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||
endif ()
|
||||
# GIT_SUBMODULES_RECURSE was added in 3.17
|
||||
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
|
||||
FetchContent_Declare(
|
||||
pico_sdk
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG master
|
||||
GIT_SUBMODULES_RECURSE FALSE
|
||||
)
|
||||
else ()
|
||||
FetchContent_Declare(
|
||||
pico_sdk
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG master
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (NOT pico_sdk)
|
||||
message("Downloading Raspberry Pi Pico SDK")
|
||||
FetchContent_Populate(pico_sdk)
|
||||
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
|
||||
endif ()
|
||||
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||
else ()
|
||||
message(FATAL_ERROR
|
||||
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
if (NOT EXISTS ${PICO_SDK_PATH})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
|
||||
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
||||
|
||||
include(${PICO_SDK_INIT_CMAKE_FILE})
|
||||
Loading…
x
Reference in New Issue
Block a user