avr_mdcart_sram_lite
diff main.c @ 5:abb348704dec
reads/writes to memory, not tested in the megadrive yet
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 12 Mar 2017 04:27:43 +0200 |
parents | test.c@bd6ad00cb1bc |
children | ff8af8351282 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/main.c Sun Mar 12 04:27:43 2017 +0200 1.3 @@ -0,0 +1,216 @@ 1.4 +/* 1.5 +Megadrive USB development cartridge prototype 1.6 +Copyright (C) 2017 John Tsiombikas <nuclear@member.fsf.org> 1.7 + 1.8 +This program is free software: you can redistribute it and/or modify 1.9 +it under the terms of the GNU General Public License as published by 1.10 +the Free Software Foundation, either version 3 of the License, or 1.11 +(at your option) any later version. 1.12 + 1.13 +This program is distributed in the hope that it will be useful, 1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.16 +GNU General Public License for more details. 1.17 + 1.18 +You should have received a copy of the GNU General Public License 1.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 1.20 +*/ 1.21 +#define F_CPU XTAL 1.22 + 1.23 +#include <stdio.h> 1.24 +#include <stdlib.h> 1.25 +#include <string.h> 1.26 +#include <ctype.h> 1.27 +#include <stdint.h> 1.28 +#include <avr/io.h> 1.29 +#include <avr/interrupt.h> 1.30 +#include <util/delay.h> 1.31 +#include "serial.h" 1.32 + 1.33 +/* pin assignments: 1.34 + * A[0,7] A0 - A7 1.35 + * C[0,7] A8 - A15 1.36 + * D2 A16 1.37 + * B[0, 7] data 1.38 + * D4 ~WE 1.39 + * D5 ~OE 1.40 + * D7 ~SYS_RESET 1.41 + */ 1.42 + 1.43 +#define A16_BIT 0x04 1.44 +#define WE_BIT 0x10 1.45 +#define OE_BIT 0x20 1.46 +#define RST_BIT 0x80 1.47 + 1.48 +#define A16_SHIFT 2 1.49 + 1.50 +#define MEM_SIZE (128L * 1024L) 1.51 + 1.52 +#define VER_STR "0.1" 1.53 + 1.54 +void proc_cmd(char *input); 1.55 +void run_mode(void); 1.56 +void prog_mode(void); 1.57 +void sram_write(uint32_t addr, unsigned char val); 1.58 +unsigned char sram_read(uint32_t addr); 1.59 + 1.60 +#define MAX_INPUT_SIZE 128 1.61 +static char input[MAX_INPUT_SIZE]; 1.62 +static unsigned char inp_cidx; 1.63 + 1.64 +uint32_t addr; 1.65 +unsigned char running; 1.66 +int echo = 0; 1.67 + 1.68 +int main(void) 1.69 +{ 1.70 + init_serial(38400); 1.71 + run_mode(); 1.72 + 1.73 + sei(); 1.74 + 1.75 + for(;;) { 1.76 + if(have_input()) { 1.77 + int c = getchar(); 1.78 + if(echo) { 1.79 + putchar(c); 1.80 + } 1.81 + 1.82 + if(c == '\r' || c == '\n') { 1.83 + input[inp_cidx] = 0; 1.84 + proc_cmd(input); 1.85 + inp_cidx = 0; 1.86 + } else if(inp_cidx < sizeof input - 1) { 1.87 + input[inp_cidx++] = c; 1.88 + } 1.89 + } 1.90 + } 1.91 + return 0; 1.92 +} 1.93 + 1.94 +void proc_cmd(char *input) 1.95 +{ 1.96 + char *endp; 1.97 + int data; 1.98 + 1.99 + switch(input[0]) { 1.100 + case 'e': 1.101 + echo = input[1] == '1' ? 1 : 0; 1.102 + printf("OK echo %s\n", echo ? "on" : "off"); 1.103 + break; 1.104 + 1.105 + case 'p': 1.106 + prog_mode(); 1.107 + printf("OK programming mode\n"); 1.108 + break; 1.109 + 1.110 + case 'b': 1.111 + run_mode(); 1.112 + printf("OK boot mode\n"); 1.113 + break; 1.114 + 1.115 + case 'a': 1.116 + addr = strtol(input + 1, &endp, 0); 1.117 + printf("OK address: %lx\n", (unsigned long)addr); 1.118 + break; 1.119 + 1.120 + case 'w': 1.121 + if(running) { 1.122 + printf("ERR running\n"); 1.123 + break; 1.124 + } 1.125 + if(addr >= MEM_SIZE) { 1.126 + printf("ERR overflow\n"); 1.127 + break; 1.128 + } 1.129 + 1.130 + data = strtol(input + 1, &endp, 0); 1.131 + sram_write(addr++, data); 1.132 + printf("OK %d\n", (int)data); 1.133 + break; 1.134 + 1.135 + case 'r': 1.136 + if(running) { 1.137 + printf("ERR running\n"); 1.138 + break; 1.139 + } 1.140 + if(addr >= MEM_SIZE) { 1.141 + printf("ERR overflow\n"); 1.142 + break; 1.143 + } 1.144 + 1.145 + data = sram_read(addr++); 1.146 + printf("OK %d\n", (int)data); 1.147 + break; 1.148 + 1.149 + default: 1.150 + printf("ERR unknown command\n"); 1.151 + break; 1.152 + } 1.153 +} 1.154 + 1.155 +void run_mode(void) 1.156 +{ 1.157 + /* tri-state everything and release the reset line */ 1.158 + DDRA = 0; 1.159 + PORTA = 0; 1.160 + DDRB = 0; 1.161 + PORTB = 0; 1.162 + DDRC = 0; 1.163 + PORTC = 0; 1.164 + DDRD = RST_BIT; 1.165 + PORTD = RST_BIT; 1.166 + 1.167 + running = 1; 1.168 +} 1.169 + 1.170 +void prog_mode(void) 1.171 +{ 1.172 + /* hold the reset line and take control of the bus */ 1.173 + PORTD = 0; 1.174 + DDRD = 0xff; 1.175 + DDRA = 0xff; 1.176 + DDRB = 0xff; 1.177 + DDRC = 0xff; 1.178 + 1.179 + running = 0; 1.180 +} 1.181 + 1.182 +void set_address(uint32_t addr) 1.183 +{ 1.184 + PORTA = addr & 0xff; 1.185 + PORTC = (addr >> 8) & 0xff; 1.186 + PORTD = (PORTD & ~A16_BIT) | ((addr >> (16 - A16_SHIFT)) & A16_BIT); 1.187 +} 1.188 + 1.189 +void sram_write(uint32_t addr, unsigned char val) 1.190 +{ 1.191 + set_address(addr); 1.192 + 1.193 + /* no need for DDRB change, we drive the bus by default in programming mode */ 1.194 + PORTB = val; /* set data */ 1.195 + 1.196 + /* pulse WE */ 1.197 + PORTD &= ~WE_BIT; 1.198 + _delay_us(0.1); 1.199 + /* WE should be low for at least 9ns, which is way faster than we can toggle it anyway */ 1.200 + PORTD |= WE_BIT; 1.201 +} 1.202 + 1.203 +unsigned char sram_read(uint32_t addr) 1.204 +{ 1.205 + unsigned char val; 1.206 + 1.207 + set_address(addr); 1.208 + 1.209 + PORTB = 0; /* make sure we won't read the previously written value */ 1.210 + 1.211 + DDRB = 0; /* release the data bus */ 1.212 + PORTD &= ~OE_BIT; /* assert OE (output enable) */ 1.213 + _delay_us(0.1); 1.214 + val = PINB; /* read the data */ 1.215 + PORTD |= OE_BIT; /* deassert OE */ 1.216 + DDRB = 0xff; /* take back the bus */ 1.217 + 1.218 + return val; 1.219 +}