avr_mdcart_sram_lite

view main.c @ 6:ff8af8351282

works
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 12 Mar 2017 23:43:41 +0200
parents abb348704dec
children f14e14abe14c
line source
1 /*
2 Megadrive USB development cartridge prototype
3 Copyright (C) 2017 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #define F_CPU XTAL
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <ctype.h>
24 #include <stdint.h>
25 #include <avr/io.h>
26 #include <avr/interrupt.h>
27 #include <util/delay.h>
28 #include "serial.h"
30 /* pin assignments:
31 * A[0,7] A0 - A7
32 * C[0,7] A8 - A15
33 * D2 A16
34 * B[0, 7] data
35 * D4 ~WE
36 * D5 ~OE
37 * D7 ~SYS_RESET
38 */
40 #define A16_BIT 0x04
41 #define WE_BIT 0x10
42 #define OE_BIT 0x20
43 #define RST_BIT 0x80
45 #define A16_SHIFT 2
47 #define MEM_SIZE (128L * 1024L)
49 #define VER_STR "0.1"
51 void proc_cmd(char *input);
52 void run_mode(void);
53 void prog_mode(void);
54 void sram_write(uint32_t addr, unsigned char val);
55 unsigned char sram_read(uint32_t addr);
57 #define MAX_INPUT_SIZE 128
58 static char input[MAX_INPUT_SIZE];
59 static unsigned char inp_cidx;
61 uint32_t addr;
62 unsigned char running;
63 int echo = 0;
65 int main(void)
66 {
67 init_serial(115200);
68 run_mode();
70 sei();
72 for(;;) {
73 if(have_input()) {
74 int c = getchar();
75 if(echo) {
76 putchar(c);
77 }
79 if(c == '\r' || c == '\n') {
80 input[inp_cidx] = 0;
81 proc_cmd(input);
82 inp_cidx = 0;
83 } else if(inp_cidx < sizeof input - 1) {
84 input[inp_cidx++] = c;
85 }
86 }
87 }
88 return 0;
89 }
91 void proc_cmd(char *input)
92 {
93 char *endp;
94 int data;
96 switch(input[0]) {
97 case 'e':
98 echo = input[1] == '1' ? 1 : 0;
99 printf("OK echo %s\n", echo ? "on" : "off");
100 break;
102 case 'p':
103 prog_mode();
104 puts("OK programming mode");
105 break;
107 case 'b':
108 run_mode();
109 puts("OK run mode");
110 break;
112 case 'a':
113 addr = strtol(input + 1, &endp, 0);
114 printf("OK address: %lx\n", (unsigned long)addr);
115 break;
117 case 'w':
118 if(running) {
119 puts("ERR running");
120 break;
121 }
122 if(addr >= MEM_SIZE) {
123 puts("ERR overflow");
124 break;
125 }
127 data = strtol(input + 1, &endp, 0);
128 sram_write(addr++, data);
129 puts("OK");
130 break;
132 case 'r':
133 if(running) {
134 puts("ERR running");
135 break;
136 }
137 if(addr >= MEM_SIZE) {
138 puts("ERR overflow");
139 break;
140 }
142 data = sram_read(addr++);
143 printf("OK %d\n", (int)data);
144 break;
146 default:
147 puts("ERR unknown command");
148 break;
149 }
150 }
152 void run_mode(void)
153 {
154 /* tri-state everything and release the reset line */
155 /* do not tri-state WE and keep it high */
156 DDRA = 0;
157 PORTA = 0;
158 DDRB = 0;
159 PORTB = 0;
160 DDRC = 0;
161 PORTC = 0;
162 DDRD = RST_BIT | WE_BIT;
163 PORTD = RST_BIT | WE_BIT;
165 running = 1;
166 }
168 void prog_mode(void)
169 {
170 /* hold the reset line and take control of the bus */
171 PORTD = WE_BIT; /* keep WE high to avoid writing random bytes */
172 DDRD = 0xff;
173 DDRA = 0xff;
174 DDRB = 0xff;
175 DDRC = 0xff;
177 running = 0;
178 }
180 void set_address(uint32_t addr)
181 {
182 PORTA = addr & 0xff;
183 PORTC = (addr >> 8) & 0xff;
184 PORTD = (PORTD & ~A16_BIT) | ((addr >> (16 - A16_SHIFT)) & A16_BIT);
185 }
187 void sram_write(uint32_t addr, unsigned char val)
188 {
189 set_address(addr);
191 /* no need for DDRB change, we drive the bus by default in programming mode */
192 PORTB = val; /* set data */
194 /* pulse WE */
195 PORTD &= ~WE_BIT;
196 /* WE should be low for at least 9ns, which is way faster than we can toggle it anyway */
197 PORTD |= WE_BIT;
198 }
200 unsigned char sram_read(uint32_t addr)
201 {
202 unsigned char val;
204 set_address(addr);
206 PORTB = 0; /* make sure we won't read the previously written value */
208 DDRB = 0; /* release the data bus */
209 PORTD &= ~OE_BIT; /* assert OE (output enable) */
210 _delay_us(0.1);
211 val = PINB; /* read the data */
212 PORTD |= OE_BIT; /* deassert OE */
213 DDRB = 0xff; /* take back the bus */
215 return val;
216 }