-
Notifications
You must be signed in to change notification settings - Fork 1
/
picocart.c
182 lines (156 loc) · 5.35 KB
/
picocart.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/**
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/clocks.h"
#include "pico/multicore.h"
#include "hardware/irq.h"
#include "board.h"
#include "grom-hw.h" // temporary during debug
#define PLL_SYS_KHZ (133 * 1000)
#ifndef PICO_DEFAULT_LED_PIN
#warning blink example requires a board with a regular LED
#define PICO_DEFAULT_LED_PIN 25
#endif
uint8_t rom_area[32*1024];
unsigned active_rom_size = 8192;
uint8_t *active_rom_area = rom_area;
void picocart_gpio_init() {
for(int i=0; i<8; i++)
gpio_init(PCn_D0+i);
gpio_init(PCnI_ROMCS);
gpio_init(PCnI_WE );
gpio_init(PCnI_GS );
gpio_init(PCnI_DBIN );
gpio_init(PCnO_CSLOA);
gpio_init(PCnO_CSHIA);
gpio_init(PCnO_CSDAT);
gpio_init(PCnO_DDIR );
gpio_init(PCnO_GRDY);
// Initially all buffers inactive
gpio_put(PCnO_CSLOA, 1);
gpio_put(PCnO_CSHIA, 1);
gpio_put(PCnO_CSDAT, 1);
gpio_put(PCnO_DDIR, 1);
gpio_put(PCnO_GRDY, 1);
// Set direction to outputs
gpio_set_dir(PCnO_CSLOA, GPIO_OUT);
gpio_set_dir(PCnO_CSHIA, GPIO_OUT);
gpio_set_dir(PCnO_CSDAT, GPIO_OUT);
gpio_set_dir(PCnO_DDIR, GPIO_OUT);
gpio_set_dir(PCnO_GRDY, GPIO_OUT);
// Set direction to inputs
gpio_set_dir(PCnI_ROMCS, GPIO_IN);
gpio_set_dir(PCnI_WE, GPIO_IN );
gpio_set_dir(PCnI_GS, GPIO_IN );
gpio_set_dir(PCnI_DBIN, GPIO_IN );
// Turn the databus in, so we're not colliding with drivers.
sio_hw->gpio_oe_clr = PCn_DATAMASK;
// Configure our debug bits.
for(int i=PCnO_DEBUG26; i<=PCnO_DEBUG27; i++) {
gpio_init(i);
gpio_put(i, 0);
gpio_set_dir(i, GPIO_OUT);
gpio_put(i, 0);
}
// Configure a special pin to read A0.
gpio_init(PCnI_BA0);
gpio_set_dir(PCnI_BA0, GPIO_IN);
}
void core1_busserver() {
// Start with GREADY low, i.e. we will stop upon GROM access
gpio_put(PCnO_GRDY, 0);
uint32_t state = save_and_disable_interrupts(); // Disable interrupts for this core.
while(1) {
rom_server();
}
}
// debug variables.
extern uint32_t rom_bank;
extern uint32_t max_bank;
extern uint32_t min_bank;
extern uint32_t bank_switches;
int main() {
// Set the system frequency to 133 MHz. vco_calc.py from the SDK tells us
// this is exactly attainable at the PLL from a 12 MHz crystal: FBDIV =
// 133 (so VCO of 1596 MHz), PD1 = 6, PD2 = 2. This function will set the
// system PLL to 133 MHz and set the clk_sys divisor to 1.
set_sys_clock_khz(PLL_SYS_KHZ, true);
// The previous line automatically detached clk_peri from clk_sys, and
// attached it to pll_usb, so that clk_peri won't be disturbed by future
// changes to system clock or system PLL. If we need higher clk_peri
// frequencies, we can attach clk_peri directly back to system PLL (no
// divider available) and then use the clk_sys divider to scale clk_sys
// independently of clk_peri.
clock_configure(
clk_peri,
0, // No glitchless mux
CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, // System PLL on AUX mux
PLL_SYS_KHZ * 1000, // Input frequency
PLL_SYS_KHZ * 1000 // Output (must be same as no divider)
);
picocart_gpio_init();
// The serial clock won't vary from this point onward, so we can configure
// the UART etc.
stdio_init_all();
init_grom_server();
multicore_launch_core1(core1_busserver);
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
gpio_put(LED_PIN, 1);
sleep_ms(100);
gpio_put(LED_PIN, 0);
sleep_ms(100);
gpio_put(LED_PIN, 1);
sleep_ms(100);
gpio_put(LED_PIN, 0);
sleep_ms(2000);
puts("Picocart has booted.\n");
// memcpy(active_rom_area, rom_mspacman_data, rom_mspacman_size);
// active_rom_size = rom_mspacman_size;
active_rom_area = rom_area;
if(ACTIVE_ROM_SIZE <= sizeof(rom_area))
memcpy(active_rom_area, ACTIVE_ROM, ACTIVE_ROM_SIZE);
else
active_rom_area = (uint8_t *)ACTIVE_ROM; // Can't copy to ROM to SRAM, try to run for external flash.
active_rom_size = ACTIVE_ROM_SIZE;
// memcpy(active_rom_area, rom_defender_data, rom_defender_size);
// active_rom_size = rom_defender_size;
puts("Cart data copied to RAM.\n");
printf("ROM_SIZE %d GROM_SIZE %d\n", ACTIVE_ROM_SIZE, ACTIVE_GROM_SIZE);
while(0) {
// Read data.
gpio_put(PCnO_DDIR, 1);
gpio_put(PCnO_CSDAT, 0);
uint32_t in = sio_hw->gpio_in;
uint32_t oe = sio_hw->gpio_hi_oe;
// Read data.
uint8_t dat = read_data();
// Read address
uint32_t a = read_address();
printf("in=%08X oe=%08X addr=%04X dat=%02X\n", in, oe, a, dat);
sleep_ms(50);
}
while( 1 ) {
sleep_ms(1000);
printf("rom_bank=%d max=%d min=%d switches=%d\n",
rom_bank, max_bank, min_bank, bank_switches
);
}
/*
const uint LED_PIN = PICO_DEFAULT_LED_PIN;
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
while (true) {
gpio_put(LED_PIN, 1);
sleep_ms(250);
gpio_put(LED_PIN, 0);
puts("LED off\n");
sleep_ms(500);
}
*/
}