Skip to content

Commit

Permalink
Initial testing of custom SPI, able to read correctly CMD, unable to …
Browse files Browse the repository at this point in the history
…answer using DAT and ACK
  • Loading branch information
dangiu committed Apr 5, 2022
1 parent 9d6dc61 commit 7299b04
Show file tree
Hide file tree
Showing 4 changed files with 349 additions and 0 deletions.
20 changes: 20 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.13)

include(pico_sdk_import.cmake)

project(test_project C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
pico_sdk_init()

add_executable(test)

pico_generate_pio_header(test ${CMAKE_CURRENT_LIST_DIR}/psxSPI.pio)

target_sources(test PRIVATE test.c)

pico_enable_stdio_uart(test 1) # enable only UART stdio

pico_add_extra_outputs(test)

target_link_libraries(test pico_stdlib hardware_pio)
62 changes: 62 additions & 0 deletions pico_sdk_import.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# 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 ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG master
)
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})
138 changes: 138 additions & 0 deletions psxSPI.pio
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
; Author: Daniele Giuliani
; Program: Simple interface to read the modified SPI protocol
; used by the PSX to communicate with controller/memory cards

.program readCmd
; Input pins mapping:
; 0 - CMD
; 1 - SEL
; 2 - CLK
wait 1 pin 1 ; initial wait to go in sync
sel_high:
wait 0 pin 1
.wrap_target
wait 0 pin 2 ; wait for clock to fall
wait 1 pin 2 ; wait for rising clock edge
jmp pin sel_high ; jumpback if SEL is high (need to be low in order to read data)
in pins 1 ; sample 1 bit from CMD line
.wrap

;.program writeDat
; Output pins mapping:
; 0 - DAT
; Input pins mapping:
; 0 - CLK
;.wrap_target
;set x, 7 ; reset counter in scratch register X
;irq wait 1 ; wait for CPU to give start
;write_bit:
;wait 1 pin 0 ; wait for clock to be high
;wait 0 pin 0 ; wait for falling clock edge
; TODO BITS MUST BE INVERTED BEFORE PLACING IN TX OR USE MUTEX TO INVERT THEM AUTOMATICALLY
;out pindirs 1 ; change direction of output bit (open collector behavior: input = leave high (1), output = set low (0))
;jmp x-- write_bit ; continue bit output until whole byte has been sent
;nop [7] ; delay of at least 1 clock cycle to allow PSX to pickup last bit
;set pindirs 0 ; deactivate ouptut (set output pin as input in order to float high)
;.wrap

.program writeDat
; Output pins mapping:
; 0 - DAT
; Input pins mapping:
; 0 - SEL
; 1 - CLK
sel_high:
out null, 32 ; clear OSR
set pindirs, 0 ; release DAT line
.wrap_target
set x, 7 ; reset counter in scratch register X
pull block
write_bit:
wait 1 pin 1 ; wait for clock to be high
wait 0 pin 1 ; wait for falling clock edge
jmp pin sel_high ; jumpback if SEL is high (need to be low in order to write data)
; TODO BITS MUST BE INVERTED BEFORE PLACING IN TX OR USE MUTEX TO INVERT THEM AUTOMATICALLY
out pindirs 1 ; change direction of output bit (open collector behavior: input = leave high (1), output = set low (0))
jmp x-- write_bit ; continue bit output until whole byte has been sent
.wrap

.program sendAck
; completely time-based, running with same clock as PSX protocol (250Khz)
; waits for interrupt from CPU then lowers ACK line for 2 clock cycles
.wrap_target
irq wait 0
set pindirs, 1 [2]
set pindirs, 0
.wrap


% c-sdk {
#define READ_CLKDIV 83 // with pico default clock (125 Mhz) results in a clock which six time the PSX clock (250 Khz) (actually slightly greater than that)
#define PSX_CLKDIV 500 // with pico default clock (125 Mhz) results in a clock equal to PSX clock (250 Khz)
#define ACK_IRQ 0
#define DAT_IRQ 1

static inline void readCmd_program_init(PIO pio, uint sm, uint offset, uint cmdPin) {
pio_sm_config c = readCmd_program_get_default_config(offset);
sm_config_set_in_pins(&c, cmdPin);
pio_sm_set_consecutive_pindirs(pio, sm, cmdPin, 3, false);
pio_gpio_init(pio, cmdPin); // CMD pin
pio_gpio_init(pio, cmdPin + 1); // SEL pin
pio_gpio_init(pio, cmdPin + 2); // CLK pin
sm_config_set_in_shift(&c, true, true, 8); // shift ISR to right, autopush every 8 bits
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); // join RX FIFO (we don't need TX fifo for this program)
sm_config_set_jmp_pin(&c, cmdPin + 1); // set SEL as jmp pin
sm_config_set_clkdiv(&c, READ_CLKDIV);

pio_sm_init(pio, sm, offset, &c);
//pio_sm_set_enabled(pio, sm, true);
}

static inline void sendAck_program_init(PIO pio, uint sm, uint offset, uint ackPin) {
pio_sm_config c = sendAck_program_get_default_config(offset);
pio_interrupt_clear(pio, ACK_IRQ); // clear interrupt if present
pio_sm_set_pins_with_mask(pio, sm, 0x00000000, 1 << ackPin); // set ACK pin to low output
pio_sm_set_consecutive_pindirs(pio, sm, ackPin, 1, false); // set ACK pin as input (initial configuration)
pio_gpio_init(pio, ackPin); // init ACK pin
sm_config_set_set_pins(&c, ackPin, 1);
sm_config_set_clkdiv_int_frac(&c, PSX_CLKDIV, 0x00);

pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}

static inline void sendAck(PIO pio) {
pio_interrupt_clear(pio, ACK_IRQ);
}

static inline void writeDat_program_init(PIO pio, uint sm, uint offset, uint datPin, uint selPin) {
pio_sm_config c = writeDat_program_get_default_config(offset);

/* Pin Configuration */
sm_config_set_in_pins(&c, selPin); // set base IN pin (SEL)
sm_config_set_out_pins(&c, datPin, 1); // set base OUT pin (DAT)
sm_config_set_set_pins(&c, datPin, 1); // set base SET pin (DAT)
pio_interrupt_clear(pio, DAT_IRQ); // clear old interrupt if present
pio_sm_set_pins_with_mask(pio, sm, 0x00000000, 1 << datPin); // set DAT pin to low output
pio_sm_set_consecutive_pindirs(pio, sm, datPin, 1, false); // set DAT pin as input (initial configuration)
pio_sm_set_consecutive_pindirs(pio, sm, selPin, 2, false); // set SEL and CLK pins as input
pio_gpio_init(pio, datPin); // init DAT pin
pio_gpio_init(pio, selPin); // init SEL pin
pio_gpio_init(pio, selPin + 1); // init CLK pin

/* FIFO configuration */
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); // join TX FIFO (we don't need RX fifo for this program)

/* Clock configuration */
//sm_config_set_clkdiv(&c, READ_CLKDIV);

/* Init SM */
pio_sm_init(pio, sm, offset, &c);
pio_sm_set_enabled(pio, sm, true);
}

static inline void sendByte(PIO pio, uint sm, uint32_t byte) {
byte = ~byte & (0x000000ff); // invert byte (0 must be ones in order to set pins to output and output low, 1 must be 0 to set pin to input and output high-z)
pio_sm_put_blocking(pio, sm, byte); // place byte in tx fifo
}
%}
129 changes: 129 additions & 0 deletions test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/pio.h"
#include "hardware/irq.h"
#include "psxSPI.pio.h"

#define PIN_DAT 5
#define PIN_CMD 6
#define PIN_SEL 7
#define PIN_CLK 8

#define PIN_ACK 9

#define ID_LO 0x41
#define ID_HI 0x5A

#define R_PRESSED 0b11111011
#define L_PRESSED 0b11111110
#define NO_PRESSED 0xff
#define SEND_ACK 0b100000000


uint smReadCmd;
uint smSendAck;
uint smWriteDat;


void pio0_irq0() {
/* SEL has gone high, reset ISR of smReadCmd (could contain garbage) before it goes low again*/
pio_sm_restart(pio0, smReadCmd);
irq_clear(PIO0_IRQ_0); // clear IRQ flag
pio_interrupt_clear(pio0, 0);
}

void process_joy_req(PIO pio) {
sendAck(pio); // acknowledge top command

uint32_t next_byte = 0;
sendByte(pio, smWriteDat, ID_LO); // write lower ID byte

next_byte = pio_sm_get_blocking(pio, smReadCmd) >> 24; // shift to get MSB
if(next_byte != 0x42) {
printf("\nWaiting for %.2x but received %.2x\n", 0x42, next_byte);
return;
} else {
printf("%.2x ", next_byte);
}
sendAck(pio);
sendByte(pio, smWriteDat, ID_HI); // write upper ID byte

next_byte = pio_sm_get_blocking(pio, smReadCmd) >> 24; // shift to get MSB
if(next_byte != 0x00) {
printf("\nWaiting for %.2x but received %.2x\n", 0x00, next_byte);
return;
} else {
printf("%.2x ", next_byte);
}
sendAck(pio);
sendByte(pio, smWriteDat, R_PRESSED); // fake right d-pad being pressed

next_byte = pio_sm_get_blocking(pio, smReadCmd) >> 24; // shift to get MSB
if(next_byte != 0x00) {
printf("\nWaiting for %.2x but received %.2x\n", 0x00, next_byte);
return;
} else {
printf("%.2x ", next_byte);
}
sendAck(pio);
sendByte(pio, smWriteDat, NO_PRESSED); // other buttons are all inactive

next_byte = pio_sm_get_blocking(pio, smReadCmd) >> 24; // shift to get MSB
if(next_byte != 0x00) {
printf("\nWaiting for %.2x but received %.2x\n", 0x00, next_byte);
return;
} else {
printf("%.2x ", next_byte);
}
// no ack and no send, transmission is over
}

int main() {
stdio_init_all();
PIO pio = pio0;

uint offsetReadCmd = pio_add_program(pio, &readCmd_program);
uint offsetSendAck = pio_add_program(pio, &sendAck_program);
uint offsetWriteDat = pio_add_program(pio, &writeDat_program);

smReadCmd = pio_claim_unused_sm(pio, true);
smSendAck = pio_claim_unused_sm(pio, true);
smWriteDat = pio_claim_unused_sm(pio, true);

sendAck_program_init(pio, smSendAck, offsetSendAck, PIN_ACK);
writeDat_program_init(pio, smWriteDat, offsetWriteDat, PIN_DAT, PIN_SEL);
readCmd_program_init(pio, smReadCmd, offsetReadCmd, PIN_CMD);

/*
selMonitor_program_init(pio, smSelMonitor, offsetSelMonitor, PIN_SEL);
irq_set_exclusive_handler(PIO0_IRQ_0, pio0_irq0);
pio_set_irq0_source_enabled(pio, pis_interrupt0, true);
irq_set_enabled(PIO0_IRQ_0, true);
*/

/*
uint32_t i = 0;
while(true) {
if(i % 1000000 == 0) {
sendAck(pio);
}
i++;
}
*/

//printf("\nSetup done, starting loop...\n");

pio_sm_set_enabled(pio, smReadCmd, true);
while(true) {
uint32_t item = pio_sm_get_blocking(pio, smReadCmd);
item >>= 24; // shift to get MSB

/* PRINT CMD RECEIVED */
printf("\n%.2x ", item);

if(item == 0x01)
process_joy_req(pio);

}
}

0 comments on commit 7299b04

Please sign in to comment.