Skip to content

Instantly share code, notes, and snippets.

@niconii
Created March 22, 2016 16:02
Show Gist options
  • Save niconii/b464a290976dd3eaa2e7 to your computer and use it in GitHub Desktop.
Save niconii/b464a290976dd3eaa2e7 to your computer and use it in GitHub Desktop.
A little SNES controller simulator
trait ControllerPins {
// inputs:
// latch pin (normally low)
fn latch_rising(&mut self);
fn latch_falling(&mut self);
// clock pin (normally high)
fn clock_rising(&mut self);
fn clock_falling(&mut self);
// output:
// data pin (high = 0, low = 1)
fn data(&self) -> bool;
}
struct SnesController {
buttons: u16,
shift_reg: u16,
data: bool
}
impl SnesController {
fn new() -> Self {
SnesController {
buttons: 0,
shift_reg: 0,
data: false
}
}
/// This only represents the state of the actual buttons, not
/// any sort of latches in the controller.
fn set_buttons(&mut self, buttons: u16) {
self.buttons = buttons;
}
/// Shifts 1 into right end, putting leftmost bit in self.data.
fn shift(&mut self) {
self.data = (self.shift_reg & 0x8000) != 0;
self.shift_reg <<= 1;
self.shift_reg |= 0x0001;
}
}
impl ControllerPins for SnesController {
fn latch_rising(&mut self) {
self.shift_reg = self.buttons & 0xfff0;
// bits 12...15 are controller id, which happens to be
// 0b0000 for a normal controller
}
fn latch_falling(&mut self) {
// Because the clock pin is normally high, the controller
// shifts the first bit on the falling edge of latch,
// so that the first bit will be read correctly.
self.shift()
}
fn clock_rising(&mut self) {
self.shift()
}
fn clock_falling(&mut self) { }
fn data(&self) -> bool {
self.data
}
}
fn main() {
let mut controller = SnesController::new();
controller.set_buttons(0b0101_0100_1010_0000);
// read buttons from controller
controller.latch_rising();
controller.latch_falling();
for _ in 0..16 {
controller.clock_falling();
print!("{}", controller.data() as u8);
controller.clock_rising();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment