Me gustaría usar un ATtiny2313 para emular un controlador Super Nintendo porque tengo un ATtiny2313 pero no tengo un registro de desplazamiento de entrada y no tengo ganas de soldar cables en una placa controladora SNES existente.
Esta aplicación requiere 12 entradas (los bits 13-16 siempre son 1) y un pin de salida de datos, reloj y pestillo.
¿Tienes este código por ahí? No puede ser más de 20 instrucciones.
Ya hay un registro de desplazamiento de 8 bits integrado en la interfaz serie universal (USI) . Todo lo que tienes que hacer es usarlo dos veces seguidas.
No tengo este código por ahí, pero tengo las siguientes mejores cosas:
Podrías decir que tengo el código por ahí, pero no está organizado y concatenado correctamente... ;)
Como dice @tyblu, todo está en el manual de la USI. En particular, lo que desea es usarlo en "Operación en modo maestro de tres cables". Eche un vistazo a la Figura 61 en la página 143 de la hoja de datos. La hoja de datos es incluso lo suficientemente amable como para proporcionar una rutina de ensamblador optimizada (8 instrucciones) (SPITransfer) para este propósito exacto:
SPITransfer:
out USIDR,r16
ldi r16,(1<<USIOIF)
out USISR,r16
ldi r16,(1<<USIWM0)|(1<<USICS1)|(1<<USICLK)|(1<<USITC)
SPITransfer_loop:
out USICR,r16
sbis USISR,USIOIF
rjmp SPITransfer_loop
in r16,USIDR
ret
Si lo conecta de modo que tenga un pin 2313 conectado al cable de "cierre" del controlador (naranja), el pin USCK se conecta al cable de "pulso" del controlador (rojo) y el pin DI se conecta al cable de "datos" del controlador. " alambre (amarillo) - deberías estar listo para irte. Según la hoja de datos, el ejemplo de código asume que los pines DO y USCK están habilitados como salidas en el registro DDRB.
Una vez que el hardware está configurado, todo lo que necesita hacer es generar un pulso alto de 12 us en el pin de "cierre", dejar caer el pin bajo para 6 us, luego llamar a la rutina de ensamblaje anterior dos veces (guardando el valor de retorno) después de cada llamada.
Encontré esta referencia muy informativa sobre la interfaz (S)NES.
El siguiente código funciona muy bien. La señal de enganche está conectada a PB5
. El SIG_PIN_CHANGE
controlador hace su trabajo en ambos bordes de la señal del pestillo, pero no importa, y la última vez que intenté agregar el cheque no funcionó.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
ISR(SIG_PIN_CHANGE)
{
USIDR = PINA | (PIND & 0b01111100) | (PINB << 7);
USISR = (1 << USIOIF); // clear overflow bit, set counter to 0
USICR |= (1 << USIOIE); // enable overflow interrupt
}
ISR(SIG_USI_OVERFLOW)
{
USIDR = (PINB << 3) | 0x0f;
USISR |= (1 << USIOIF); // clear overflow bit
USICR &= (0xff ^ (1 << USIOIE)); // disable overflow interrupt
}
int main() {
USIDR = 0xff;
USICR = (1 << USIWM0) | (1 << USICS1); // 3-wire mode; external, positive edge.
DDRA = 0;
DDRD = 0;
DDRB = 1 << 6; // MISO
// Enable pullups
PORTA = 0x3;
PORTB = 0b11111;
PORTD = 0xfc;
// USIDR is shifted out MSB first.
// pin change interrupt for latch pin
PCMSK = (1 << 5);
GIMSK |= (1 << PCIE);
sei();
while (1) {
sleep_mode();
}
}
-Os
para optimizar el tamaño y -fwhole-program
cuando construyo todo a la vez. Ahorra algo de espacio y generalmente acelera las cosas. Para hacer coincidir con precisión el controlador, desea aceptar el bloqueo en cualquier momento (razón por la cual los controladores SNES funcionan en NES, que solo lee 8 bits). Para errores tipográficos: hola se lee desde PORTD
en lugar de PORTB
, y debe usar PINB
y PIND
de todos modos para leer las entradas. Posiblemente quiera enmascarar D7 usando PIND&0x7f
también.|
emite la sbi
instrucción cuando es posible. De acuerdo con la hoja de datos, a diferencia de la mayoría de los indicadores de interrupción, USIOIF
solo se borra con un 1
y no se borra automáticamente cuando regresa el controlador de interrupción.sbi
está limitado a los 32 registros de E/S inferiores, pero el USI está en ese rango en el tiny2313. Lo que conduce a una peculiaridad extraña: PORTA|=1; PORTA|=2;
es más rápido que PORTA|=3;
, ya que este último compila en 3 instrucciones (pero establece ambos bits en el mismo ciclo). No es tu problema, solo una peculiaridad.
vicatcu
joeforker
toby jaffey