-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdragon.c
174 lines (148 loc) · 4.09 KB
/
dragon.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
/********************************************************************
* dragon.c
*
* DRAGON DATA computer emulator, main module.
* With MC6809E CPU emulation.
*
* February 6, 2021
*
*******************************************************************/
#include "printf.h"
#include "mem.h"
#include "cpu.h"
#include "rpi.h"
#include "gpio.h"
#include "sam.h"
#include "vdg.h"
#include "pia.h"
#include "loader.h"
/* -----------------------------------------
Dragon 32 ROM image
----------------------------------------- */
#include "dragon/dragon.h"
/* -----------------------------------------
Module definition
----------------------------------------- */
#define DRAGON_ROM_START 0x8000
#define DRAGON_ROM_END 0xfeff
#define ESCAPE_LOADER 1 // Pressing F1
#define LONG_RESET_DELAY 1500000 // Micro-seconds to force cold start
#define VDG_RENDER_CYCLES 4500 // CPU cycle count for ~20mSec screen refresh rate
#define CPU_TIME_WASTE 1500 // Results in a CPU cycle of 4uSec
/* -----------------------------------------
Module functions
----------------------------------------- */
static int get_reset_state(uint32_t time);
/*------------------------------------------------
* main()
*
*/
#if (RPI_BARE_METAL==1)
void kernel(uint32_t r0, uint32_t machid, uint32_t atags)
#else
int main(int argc, char *argv[])
#endif
{
int i;
int emulator_escape_code;
int vdg_render_cycles = 0;
if ( rpi_gpio_init() == -1 )
{
rpi_halt();
}
printf("Dragon 32 bare metal %s %s\n", __DATE__, __TIME__);
printf("GPIO initialized.\n");
/* ROM code load
*/
printf("Loading ROM ... ");
i = 0;
while ( code[i] != -1 )
{
mem_write(i + LOAD_ADDRESS, code[i]);
i++;
}
printf("Loaded %i bytes.\n", i - 1);
mem_define_rom(DRAGON_ROM_START, DRAGON_ROM_END);
/* Emulation initialization
*/
sam_init();
pia_init();
vdg_init();
printf("Initializing CPU.\n");
cpu_init(RUN_ADDRESS);
/* CPU endless execution loop.
*/
printf("Starting CPU.\n");
cpu_reset(1);
for (;;)
{
//rpi_testpoint_on();
cpu_run();
//rpi_testpoint_off();
bcm2835_crude_delay(2);
switch ( get_reset_state(LONG_RESET_DELAY) )
{
case 0:
cpu_reset(0);
break;
case 2:
/* Cold start flag set to value that is not 0x55
*/
mem_write(0x71, 0);
printf("Force cold restart.\n");
/* no break */
case 1:
cpu_reset(1);
break;
default:
printf("kernel(): unknown reset state.\n");
}
emulator_escape_code = pia_function_key();
if ( emulator_escape_code == ESCAPE_LOADER )
loader();
vdg_render_cycles++;
if ( vdg_render_cycles == VDG_RENDER_CYCLES )
{
rpi_testpoint_on();
vdg_render();
rpi_testpoint_off();
pia_vsync_irq();
vdg_render_cycles = 0;
}
}
#if (RPI_BARE_METAL==0)
return 0;
#endif
}
/*------------------------------------------------
* get_reset_state()
*
* Scan the reset button with rpi_reset_button() and return
* '1' for short reset and '2' for long reset press.
* '0' for no press.
* Accepts 'time' in micro-seconds as a parameter for determining long
* press.
*
* param: minimum button press time in micro-seconds
* return: '0'=no press, '1'=short reset, '2'=long reset press.
*
*/
static int get_reset_state(uint32_t time)
{
uint32_t start_time;
int reset_type = 0;
if ( rpi_reset_button() == 0 ) // Active low!
{
start_time = rpi_system_timer();
while ( !rpi_reset_button() );
if ( (rpi_system_timer() - start_time) >= time )
{
reset_type = 2;
}
else
{
reset_type = 1;
}
}
return reset_type;
}