Permalink
Browse files

Fix for Nunchuk double zero write

  • Loading branch information...
lawrie committed Sep 23, 2018
1 parent e906ab2 commit 17f26fade5c6aceb7c80fb8baf5057c06612b3a8
@@ -0,0 +1,22 @@
FIRMWARE_DIR = ../../firmware
HDL_DIR = ../../hdl
INCLUDE_DIR = ../../libraries
VERILOG_FILES = \
$(HDL_DIR)/top.v \
$(HDL_DIR)/picosoc/memory/spimemio.v \
$(HDL_DIR)/picosoc/uart/simpleuart.v \
$(HDL_DIR)/picosoc/picosoc.v \
$(HDL_DIR)/picorv32/picorv32.v \
$(HDL_DIR)/picosoc/nunchuk/I2C_master.v \
$(HDL_DIR)/picosoc/i2c/i2c.v \
$(HDL_DIR)/picosoc/gpio/gpio.v

PCF_FILE = $(HDL_DIR)/pins.pcf
LDS_FILE = $(FIRMWARE_DIR)/sections.lds
START_FILE = $(FIRMWARE_DIR)/start.S
C_FILES = main.c \
$(INCLUDE_DIR)/uart/uart.c \
$(INCLUDE_DIR)/nunchuk/nunchuk.c
DEFINES = -Dgpio -Di2c

include $(HDL_DIR)/tiny_soc.mk
@@ -0,0 +1,71 @@
#include <stdint.h>
#include <stdbool.h>
#include <nunchuk/nunchuk.h>
#include <uart/uart.h>

// a pointer to this is a null pointer, but the compiler does not
// know that because "sram" is a linker symbol from sections.lds.
extern uint32_t sram;

#define reg_spictrl (*(volatile uint32_t*)0x02000000)
#define reg_uart_clkdiv (*(volatile uint32_t*)0x02000004)

uint32_t set_irq_mask(uint32_t mask); asm (
".global set_irq_mask\n"
"set_irq_mask:\n"
".word 0x0605650b\n"
"ret\n"
);

void irq_handler(uint32_t irqs, uint32_t* regs) { }

void delay(uint32_t n) {
for (uint32_t i = 0; i < n; i++) asm volatile ("");
}

void main() {
reg_uart_clkdiv = 139;

set_irq_mask(0xff);

// switch to dual IO mode
reg_spictrl = (reg_spictrl & ~0x007F0000) | 0x00400000;

// Initialize the Nunchuk
i2c_send_cmd(0x40, 0x00);

uint32_t timer = 0;

while (1) {
timer = timer + 1;

if ((timer & 0xffff) == 0xffff) {
i2c_send_reg(0x00);
delay(100);
uint8_t jx = i2c_read();
print("Joystick x: ");
print_hex(jx, 2);
print("\n");
uint8_t jy = i2c_read();
print("Joystick y: ");
print_hex(jy, 2);
print("\n");
uint8_t ax = i2c_read();
print("Acceleration x: ");
print_hex(ax, 2);
print("\n");
uint8_t ay = i2c_read();
print("Acceleration y: ");
print_hex(ay, 2);
print("\n");
uint8_t az = i2c_read();
print("Acceleration z: ");
print_hex(az, 2);
print("\n");
uint8_t rest = i2c_read();
print("Buttons: ");
print_hex(rest & 3, 2);
print("\n");
}
}
}
@@ -279,8 +279,8 @@ else
begin
status[29] <= sda; // SDA should be driven low for slave ACK
end
if ((bit_count == 18) & read // Reading and past first data ack
|| (bit_count == 36) || (ctrl_reg[31] && bit_count == 27)) // Past first or second data ack
if ((bit_count == 18 && (read || ~ctrl_reg[31])) // Register-only write or write-cycle read
|| bit_count == 27) // Register and single data byte
begin
timer <= t_su_sto; // 4.0us from spec
rtn_state <= stop;
@@ -13,6 +13,10 @@ void i2c_write(uint8_t r, uint8_t d) {
reg_i2c_write = (ADDRESS << 24) | (r << 16) | (d << 8) | 0x80000000;
}

void i2c_write_reg(uint8_t r) {
reg_i2c_write = (ADDRESS << 24) | (r << 16);
}

void i2c_send_cmd(uint8_t r, uint8_t d) {
uint32_t status;

@@ -23,6 +27,16 @@ void i2c_send_cmd(uint8_t r, uint8_t d) {
} while ((status >> 31) != 0);
}

void i2c_send_reg(uint8_t r) {
uint32_t status;

i2c_write_reg(r);

do {
status = i2c_get_status();
} while ((status >> 31) != 0);
}

uint8_t i2c_read(void) { // Read without write cycle
uint32_t status;

@@ -7,8 +7,12 @@ uint32_t i2c_get_status(void);

void i2c_write(uint8_t r, uint8_t d);

void i2c_writei_reg(uint8_t r);

void i2c_send_cmd(uint8_t r, uint8_t d);

void i2c_send_reg(uint8_t r);

uint8_t i2c_read(void);

#endif

0 comments on commit 17f26fa

Please sign in to comment.