我正在为两个 SNES 控制器构建发射器和接收器对,因为我不喜欢使用长延长线让控制器到达沙发。我将ATmega328Ps用于 AVR,带有 RF24l01 无线收发器(使用 ManiacBugs RF24 库)。我在发射器上使用修改后的 snesPad 库来轮询两个控制器的按钮状态并将它们作为 32 位无符号长返回,然后将其传输到接收器。所有标准库,没有问题(到目前为止)。
然而,在接收端,我必须正确响应来自 SNES 的锁存器和时钟信号,我还没有找到任何库存库。对于那些不熟悉 SNES 控制器的人来说,它们基本上是两个 8 位并行到串行移位寄存器串联。它们在锁存信号的上升沿(12 µs 脉冲高电平,通常为低电平)锁存所有按钮状态,在锁存器的下降沿驱动第一位,然后在时钟的上升沿驱动每个连续的位(6 µs 延迟从锁存器下降,通常为高,6 µs 低 - 6 µs 高周期)。
我决定使用外部中断来触发锁存脉冲和每个时钟脉冲的正确行为。不过,我是编程 Arduinos 的新手,也是 C/C++ 的新手。虽然我的代码可以编译,但我不确定它是否真的能按预期运行。如果对 AVR 有一定经验的人可以看看我的代码并告诉我它是否可以工作,如果不行,在哪里以及为什么,我将非常感激!
Arduino草图如下:
/*
Copyright (C) 2012 John Byers <jbyers2@wgu.edu>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 3 as published by the Free Software Foundation
*/
/**
* Dual Wireless Retro Controller Adapter Transmitter
*
* This is the reciever side code for the adapter set.
*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <RF24_config.h>
//
// Hardware Configuration
//
RF24 radio(9,10);
//
// Variable Inits
//
volatile unsigned long state2 = 0xFFFFFFFF;
volatile byte i = 0;
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
int strobe = 2;
int clock = 3;
volatile int data1 = 5;
volatile int data2 = 6;
bool firstLoop = true;
volatile int status2 = 1;
void setup()
{
radio.begin();
radio.setRetries(0,15);
radio.enableDynamicPayloads();
Serial.begin(57600);
pinMode(strobe, INPUT);
pinMode(clock, INPUT);
pinMode(data1, OUTPUT); digitalWrite(data1, LOW);
pinMode(data2, OUTPUT); digitalWrite(data2, LOW);
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1,pipes[0]);
//
//Dump the configuration of the RF unit for debugging
//
radio.printDetails();
//
//Setup Interupts
//
attachInterrupt(strobe,latch,RISING);
attachInterrupt(clock,data,RISING);
}
void loop()
{
if (firstLoop) {
int status1 = 1;
bool ok = radio.write( &status1, sizeof(int));
firstLoop = false;
radio.startListening();
if (!ok) {
Serial.println("sync packet transmission failed");
}
else {
Serial.println("sync packet transmission successful");
}
}
if ( radio.available() )
{
unsigned long state = 0;
radio.read( &state, sizeof(unsigned long) );
Serial.println(state, BIN);
state2 = state;
}
else
{
Serial.println("No data recieved yet");
}
}
//Latch interrupt routine
void latch()
{
i = 0;
digitalWrite(data1,HIGH);
digitalWrite(data2,HIGH);
digitalWrite(data1,bitRead(state2,i));
digitalWrite(data2,bitRead(state2,(i+16)));
Serial.println("Bit0 out");
}
//Data interrupt routine
void data()
{
i++;
digitalWrite(data1,bitRead(state2,i));
digitalWrite(data2,bitRead(state2,(i+16)));
Serial.print("Bit");
Serial.print(i);
Serial.println(" out");
if(i=15)
{
digitalWrite(data1,LOW);
digitalWrite(data2,LOW);
radio.stopListening();
int status1 = status2;
bool ok = radio.write( &status1, sizeof(int));
if (!ok) {
Serial.println("sync packet transmission failed");
}
else {
Serial.println("sync packet transmission successful");
}
radio.startListening();
}
}