Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add trackball module(paw3204) support for choco60
  • Loading branch information
kabocha committed Apr 30, 2020
1 parent a4d2fa4 commit 4ea73b0
Show file tree
Hide file tree
Showing 9 changed files with 365 additions and 6 deletions.
3 changes: 0 additions & 3 deletions choco60_track.c
Expand Up @@ -19,8 +19,6 @@
// You can leave any or all of these undefined.
// These are only required if you want to perform custom actions.

/*
void matrix_init_kb(void) {
// put your keyboard start-up code here
// runs once when the firmware starts up
Expand Down Expand Up @@ -48,4 +46,3 @@ void led_set_kb(uint8_t usb_led) {
led_set_user(usb_led);
}

*/
2 changes: 2 additions & 0 deletions config.h
Expand Up @@ -53,3 +53,5 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define SOFT_SERIAL_PIN D3 // or D1, D2, D3, E6
#define SPLIT_HAND_PIN D0

#define SERIAL_USE_MULTI_TRANSACTION
45 changes: 45 additions & 0 deletions keymaps/default/keymap.c
Expand Up @@ -16,6 +16,9 @@

#include QMK_KEYBOARD_H

#include "paw3204.h"
#include "pointing_device.h"

enum layer_names {
_BASE,
_FN,
Expand All @@ -39,3 +42,45 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______, _______, _______, _______, _______, KC_STOP, _______
)
};


report_mouse_t mouse_rep;

void matrix_init_user(void) {
init_paw3204();
}

void matrix_scan_user(void) {
static int cnt;
static bool paw_ready;
if (cnt++ % 50 == 0) {
uint8_t pid = read_pid_paw3204();
if (pid == 0x30) {
dprint("paw3204 OK\n");
paw_ready = true;
} else {
dprintf("paw3204 NG:%d\n", pid);
paw_ready = false;
}
}

if (paw_ready) {
uint8_t stat;
int8_t x, y;

read_paw3204(&stat, &x, &y);
mouse_rep.buttons = 0;
mouse_rep.h = 0;
mouse_rep.v = 0;
mouse_rep.x = y;
mouse_rep.y = -x;

if (cnt % 10 == 0) {
// dprintf("stat:%3d x:%4d y:%4d\n", stat, mouse_rep.x, mouse_rep.y);
}

if (stat & 0x80) {
pointing_device_set_report(mouse_rep);
}
}
}
119 changes: 119 additions & 0 deletions keymaps/default/paw3204.c
@@ -0,0 +1,119 @@
/*
Copyright 2019 Sekigon
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "quantum.h"
#include "paw3204.h"

#define READ(addr) (addr)
#define WRITE(addr) (0x80 | addr)

#define REG_PID1 0x00
#define REG_PID2 0x01
#define REG_STAT 0x02
#define REG_X 0x03
#define REG_Y 0x04

typedef int (*spi_paw3204_t)(uint8_t *p_tx_buffer, size_t tx_length, uint8_t *p_rx_buffer, size_t rx_length, uint8_t cs_pin);

#ifndef PAW3204_SCLK
# define PAW3204_SCLK D4 //please check unused pin.
#endif

#ifndef PAW3204_DATA
# define PAW3204_DATA D2 //please check unused pin.
#endif

int spi_soft_half_duplex(uint8_t *p_tx_buffer, size_t tx_length, uint8_t *p_rx_buffer, size_t rx_length, uint8_t cs_pin) {
if (tx_length != 2 || rx_length != 2) {
p_rx_buffer[1] = 0xFF;
return 1;
}

writePin(PAW3204_DATA, readPin(PAW3204_DATA));
setPinOutput(PAW3204_DATA);

for (int8_t idx = 7; idx >= 0; idx--) {
writePinLow(PAW3204_SCLK);
writePin(PAW3204_DATA, (p_tx_buffer[0] >> idx) & 1);
writePinHigh(PAW3204_SCLK);
}

_delay_us(5);
setPinInputHigh(PAW3204_DATA);

p_rx_buffer[1] = 0;
for (int8_t idx = 7; idx >= 0; idx--) {
writePinLow(PAW3204_SCLK);
writePinHigh(PAW3204_SCLK);
p_rx_buffer[1] |= readPin(PAW3204_DATA) << idx;
}

return 0;
}

// spi_paw3204_t spi_paw3204 = spim_start;
spi_paw3204_t spi_paw3204 = spi_soft_half_duplex;

uint8_t read_pid_paw3204() {
uint8_t snd[] = {READ(REG_PID1), 0xFF};
uint8_t rcv[] = {0xFF, 0xFF};

spi_paw3204(snd, sizeof(snd), rcv, sizeof(rcv), 0xFF);

return rcv[1];
}

// set IO pins
void init_paw3204() {
setPinOutput(PAW3204_SCLK);
setPinInputHigh(PAW3204_DATA);
}

int read_paw3204(uint8_t *stat, int8_t *x, int8_t *y) {
{
uint8_t snd[] = {READ(REG_STAT), 0xFF};
uint8_t rcv[] = {0xFF, 0xFF};

spi_paw3204(snd, sizeof(snd), rcv, sizeof(rcv), 0xFF);
*stat = rcv[1];
}
{
uint8_t snd[] = {READ(REG_X), 0xFF};
uint8_t rcv[] = {0xFF, 0xFF};

spi_paw3204(snd, sizeof(snd), rcv, sizeof(rcv), 0xFF);
*x = *((int8_t *)(rcv + 1));
}
{
uint8_t snd[] = {READ(REG_Y), 0xFF};
uint8_t rcv[] = {0xFF, 0xFF};

spi_paw3204(snd, sizeof(snd), rcv, sizeof(rcv), 0xFF);
*y = *((int8_t *)(rcv + 1));
}
return 1;
}

void read_all_paw3204(paw3204_all_reg *dat) {
for (uint8_t idx = 0; idx < sizeof(paw3204_all_reg); idx++) {
uint8_t snd[] = {READ(idx), 0xFF};
uint8_t rcv[] = {0xFF, 0xFF};

spi_paw3204(snd, sizeof(snd), rcv, sizeof(rcv), 0xFF);
dat->reg[idx] = rcv[1];
}
}
13 changes: 13 additions & 0 deletions keymaps/default/paw3204.h
@@ -0,0 +1,13 @@

#pragma once

#include <stdint.h>

typedef union {
uint8_t reg[8];
} paw3204_all_reg;

uint8_t read_pid_paw3204(void);
void init_paw3204(void);
int read_paw3204(uint8_t *stat, int8_t *x, int8_t *y);
void read_all_paw3204(paw3204_all_reg *dat);
65 changes: 65 additions & 0 deletions matrix.c
@@ -0,0 +1,65 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

/*
* scan matrix
*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "print.h"
#include "debug.h"
#include "util.h"
#include "matrix.h"
#include "pro_micro.h"

#include "split_scomm.h"

#ifndef DEBOUNCE
# define DEBOUNCE 5
#endif

#define ERROR_DISCONNECT_COUNT 5

static const int ROWS_PER_HAND = MATRIX_ROWS/2;
uint8_t is_master = 0 ;

static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;

__attribute__ ((weak))
void matrix_init_kb(void) {
matrix_init_user();
}

__attribute__ ((weak))
void matrix_scan_kb(void) {
matrix_scan_user();
}

__attribute__ ((weak))
void matrix_init_user(void) {
}

__attribute__ ((weak))
void matrix_scan_user(void) {
}

60 changes: 57 additions & 3 deletions rules.mk
@@ -1,21 +1,69 @@
# MCU name
MCU = atmega32u4

# Processor frequency.
# This will define a symbol, F_CPU, in all source code files equal to the
# processor frequency in Hz. You can then use this symbol in your source code to
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
# automatically to create a 32-bit value in your source code.
#
# This will be an integer division of F_USB below, as it is sourced by
# F_USB after it has run through any CPU prescalers. Note that this value
# does not *change* the processor frequency - it should merely be updated to
# reflect the processor speed set externally so that the code can use accurate
# software delays.
F_CPU = 16000000


#
# LUFA specific
#
# Target architecture (see library "Board Types" documentation).
ARCH = AVR8

# Input clock frequency.
# This will define a symbol, F_USB, in all source code files equal to the
# input clock frequency (before any prescaling is performed) in Hz. This value may
# differ from F_CPU if prescaling is used on the latter, and is required as the
# raw input clock is fed directly to the PLL sections of the AVR for high speed
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
# at the end, this will be done automatically to create a 32-bit value in your
# source code.
#
# If no clock division is performed on the input clock inside the AVR (via the
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
F_USB = $(F_CPU)

# Interrupt driven control endpoint task(+60)
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT


# Bootloader selection
# Teensy halfkay
# Pro Micro caterina
# Atmel DFU atmel-dfu
# LUFA DFU lufa-dfu
# QMK DFU qmk-dfu
# ATmega32A bootloadHID
# ATmega328P USBasp
# atmega32a bootloadHID
BOOTLOADER = caterina
#BOOTLOADER = atmel-dfu


# If you don't know the bootloader type, then you can specify the
# Boot Section Size in *bytes* by uncommenting out the OPT_DEFS line
# Teensy halfKay 512
# Teensy++ halfKay 1024
# Atmel DFU loader 4096
# LUFA bootloader 4096
# USBaspLoader 2048
# OPT_DEFS += -DBOOTLOADER_SIZE=4096


# Build Options
# change yes to no to disable
#
BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
MOUSEKEY_ENABLE = no # Mouse keys(+4700)
MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
CONSOLE_ENABLE = no # Console for debug(+400)
COMMAND_ENABLE = no # Commands for debug and configuration
Expand All @@ -33,3 +81,9 @@ FAUXCLICKY_ENABLE = no # Use buzzer to emulate clicky switches
HD44780_ENABLE = no # Enable support for HD44780 based LCDs (+400)

SPLIT_KEYBOARD = yes # Enable split keyboard

POINTING_DEVICE_ENABLE = yes
SRC += \
split_scomm.c \
matrix.c \
paw3204.c \

0 comments on commit 4ea73b0

Please sign in to comment.