Hard fork initial commit
This commit contains the kicad files for the PCB, the updated firmware for this new pcb design.
33
.gitignore
vendored
@ -1,3 +1,34 @@
|
||||
build/
|
||||
.vscode/
|
||||
.DS_Store
|
||||
|
||||
|
||||
# For PCBs designed using KiCad: https://www.kicad.org/
|
||||
# Format documentation: https://kicad.org/help/file-formats/
|
||||
|
||||
# Temporary files
|
||||
*.000
|
||||
*.bak
|
||||
*.bck
|
||||
*.kicad_pcb-bak
|
||||
*.kicad_sch-bak
|
||||
*-backups
|
||||
*.kicad_prl
|
||||
*.sch-bak
|
||||
*~
|
||||
_autosave-*
|
||||
*.tmp
|
||||
*-save.pro
|
||||
*-save.kicad_pcb
|
||||
fp-info-cache
|
||||
|
||||
# Netlist files (exported from Eeschema)
|
||||
*.net
|
||||
|
||||
# Autorouter files (exported from Pcbnew)
|
||||
*.dsn
|
||||
*.ses
|
||||
|
||||
# Exported BOM files
|
||||
*.xml
|
||||
*.csv
|
||||
*.lck
|
@ -1,107 +0,0 @@
|
||||
#define CHANNELS 4
|
||||
|
||||
// SAMPLE_CACHE_LENGTH must be power of 2 (8, 16, 32, etc.)
|
||||
// See cache.h for implementation
|
||||
#define SAMPLE_CACHE_LENGTH 16
|
||||
|
||||
// The thresholds are also dependent on SAMPLE_CACHE_LENGTH, if you
|
||||
// changed SAMPLE_CACHE_LENGTH, you should also adjust thresholds
|
||||
#define HIT_THRES 750
|
||||
#define RESET_THRES 200
|
||||
|
||||
// Sensitivity multipliers for each channel, 1.0 as the baseline
|
||||
#define L_DON_SENS 1.0
|
||||
#define L_KAT_SENS 1.0
|
||||
#define R_DON_SENS 1.0
|
||||
#define R_KAT_SENS 1.0
|
||||
|
||||
// Input pins for each channel
|
||||
#define L_DON_IN A0
|
||||
#define L_KAT_IN A1
|
||||
#define R_DON_IN A2
|
||||
#define R_KAT_IN A3
|
||||
|
||||
// Output LED pins for each channel (just for visualization)
|
||||
#define L_DON_LED 5
|
||||
#define L_KAT_LED 6
|
||||
#define R_DON_LED 7
|
||||
#define R_KAT_LED 8
|
||||
|
||||
// Keyboard output for each channel
|
||||
#define L_DON_KEY 'f'
|
||||
#define L_KAT_KEY 'd'
|
||||
#define R_DON_KEY 'j'
|
||||
#define R_KAT_KEY 'k'
|
||||
|
||||
// Enable debug mode to view analog input values from the Serial
|
||||
// Enabling this also disables the keyboard simulation
|
||||
#define DEBUG 0
|
||||
|
||||
#include <Keyboard.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "cache.h"
|
||||
|
||||
Cache<int, SAMPLE_CACHE_LENGTH> inputWindow[CHANNELS];
|
||||
unsigned long power[CHANNELS];
|
||||
unsigned long lastPower[CHANNELS];
|
||||
|
||||
bool triggered;
|
||||
unsigned long triggeredTime[CHANNELS];
|
||||
|
||||
const byte inPins[] = {L_DON_IN, L_KAT_IN, R_DON_IN, R_KAT_IN};
|
||||
const byte outPins[] = {L_DON_LED, L_KAT_LED, R_DON_LED, R_KAT_LED};
|
||||
const char outKeys[] = {L_DON_KEY, L_KAT_KEY, R_DON_KEY, R_KAT_KEY};
|
||||
float sensitivities[] = {L_DON_SENS, L_KAT_SENS, R_DON_SENS, R_KAT_SENS};
|
||||
|
||||
short maxIndex;
|
||||
float maxPower;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Keyboard.begin();
|
||||
analogReference(DEFAULT);
|
||||
for (byte i = 0; i < CHANNELS; i++) {
|
||||
power[i] = 0;
|
||||
lastPower[i] = 0;
|
||||
triggered = false;
|
||||
}
|
||||
maxIndex = -1;
|
||||
maxPower = 0;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (maxIndex != -1 && lastPower[maxIndex] < RESET_THRES) {
|
||||
triggered = false;
|
||||
digitalWrite(outPins[maxIndex], LOW);
|
||||
maxIndex = -1;
|
||||
maxPower = 0;
|
||||
}
|
||||
|
||||
for (byte i = 0; i < CHANNELS; i++) {
|
||||
inputWindow[i].put(analogRead(inPins[i]));
|
||||
power[i] = sensitivities[i] *
|
||||
(power[i] - inputWindow[i].get(1) + inputWindow[i].get());
|
||||
|
||||
if (lastPower[i] > maxPower && power[i] < lastPower[i]) {
|
||||
maxPower = lastPower[i];
|
||||
maxIndex = i;
|
||||
}
|
||||
lastPower[i] = power[i];
|
||||
#if DEBUG
|
||||
Serial.print(power[i]);
|
||||
Serial.print(" ");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!triggered && maxPower >= HIT_THRES) {
|
||||
triggered = true;
|
||||
digitalWrite(outPins[maxIndex], HIGH);
|
||||
#if !DEBUG
|
||||
Keyboard.print(outKeys[maxIndex]);
|
||||
#endif
|
||||
}
|
||||
#if DEBUG
|
||||
Serial.print("\n");
|
||||
#endif
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/***************************************************************
|
||||
* *
|
||||
* Taiko Sanro - Arduino *
|
||||
* Cache data structure *
|
||||
* *
|
||||
* Chris *
|
||||
* wisaly@gmail.com *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
#ifndef CACHE_H
|
||||
#define CACHE_H
|
||||
|
||||
template <class T, int L>
|
||||
class Cache {
|
||||
public:
|
||||
Cache() { memset(data_, 0, sizeof(data_)); }
|
||||
inline void put(T value) {
|
||||
current_ = (current_ + 1) & (L - 1);
|
||||
data_[current_] = value;
|
||||
}
|
||||
inline T get(int offset = 0) const {
|
||||
return data_[(current_ + offset) & (L - 1)];
|
||||
}
|
||||
|
||||
private:
|
||||
T data_[L];
|
||||
int current_ = 0;
|
||||
};
|
||||
|
||||
#endif // CACHE_H
|
@ -1,25 +0,0 @@
|
||||
/********************************************************
|
||||
|
||||
ESP32 is not fast enough to process 16 channels of input
|
||||
simultaneously, so you can choose one of the 2 modes:
|
||||
|
||||
- MODE_TWO_PLAYERS: Allows the controller to connect 2
|
||||
drums, but the sensitivity values are flashed to the
|
||||
board so you can't adjust them without re-flash the
|
||||
firmware. If you use the provided board, connect the
|
||||
2 drums and ignore the adjustable resistors.
|
||||
|
||||
- MODE_ADJUSTABLE: Allows you to adjust the sensitivity
|
||||
values with the potentiometer as you play, but only
|
||||
the P1 side of the board will be enabled (you can
|
||||
configurate it as 1P or 2P in Params.h file).
|
||||
|
||||
**********************************************************/
|
||||
|
||||
#define MODE_TWO_PLAYERS
|
||||
|
||||
#ifdef MODE_TWO_PLAYERS
|
||||
#include "two_players.h"
|
||||
#elif defined(MODE_ADJUSTABLE)
|
||||
#include "adjustable.h"
|
||||
#endif
|
|
@ -1,122 +0,0 @@
|
||||
#include "params.h"
|
||||
|
||||
const byte inPins[CHANNELS] = {
|
||||
P1_L_DON_IN, P1_L_KAT_IN, P1_R_DON_IN, P1_R_KAT_IN
|
||||
};
|
||||
const byte sensitivityPins[CHANNELS] = {
|
||||
P1_L_DON_SENS_IN, P1_L_KAT_SENS_IN, P1_R_DON_SENS_IN, P1_R_KAT_SENS_IN
|
||||
};
|
||||
|
||||
Cache<int, SAMPLE_CACHE_LENGTH> inputWindow[CHANNELS];
|
||||
unsigned long power[CHANNELS];
|
||||
|
||||
#ifndef RAW_ANALOG_MODE
|
||||
unsigned long lastPower[PLAYERS][CHANNELS];
|
||||
bool triggered[PLAYERS];
|
||||
unsigned long triggeredTime[PLAYERS][CHANNELS];
|
||||
int outputValue[PLAYERS] = {0, 0};
|
||||
uint resetTimer[PLAYERS] = {0, 0};
|
||||
short maxIndex[PLAYERS] = {0, 0};
|
||||
float maxPower[PLAYERS] = {0, 0};
|
||||
#endif
|
||||
|
||||
uint axisValues[CHANNELS] = {0, 0, 0, 0};
|
||||
|
||||
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_GAMEPAD, 10, 4,
|
||||
true, true, false, true, true, false,
|
||||
false, false, false, false, false);
|
||||
|
||||
void setup() {
|
||||
for (byte i = 0; i < CHANNELS; i++) {
|
||||
power[i] = 0;
|
||||
#ifndef RAW_ANALOG_MODE
|
||||
lastPower[i] = 0;
|
||||
triggered = false;
|
||||
#endif
|
||||
pinMode(inPins[i], INPUT);
|
||||
pinMode(sensitivityPins[i], INPUT);
|
||||
}
|
||||
#ifndef RAW_ANALOG_MODE
|
||||
maxIndex = -1;
|
||||
maxPower = 0;
|
||||
#endif
|
||||
USB.PID(0x4869);
|
||||
USB.VID(0x4869);
|
||||
USB.productName("Taiko Controller");
|
||||
USB.manufacturerName("GitHub Community");
|
||||
USB.begin();
|
||||
Joystick.begin(false);
|
||||
Joystick.setXAxisRange(-AXIS_RANGE, AXIS_RANGE);
|
||||
Joystick.setYAxisRange(-AXIS_RANGE, AXIS_RANGE);
|
||||
Joystick.setRxAxisRange(-AXIS_RANGE, AXIS_RANGE);
|
||||
Joystick.setRyAxisRange(-AXIS_RANGE, AXIS_RANGE);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
for (byte i = 0; i < CHANNELS; i++) {
|
||||
inputWindow[i].put(analogRead(inPins[i]));
|
||||
power[i] = power[i] - inputWindow[i].get(1) + inputWindow[i].get();
|
||||
#ifndef RAW_ANALOG_MODE
|
||||
if (lastPower[i] > maxPower && power[i] < lastPower[i]) {
|
||||
maxPower = lastPower[i];
|
||||
maxIndex = i;
|
||||
}
|
||||
lastPower[i] = power[i];
|
||||
#else
|
||||
float x = analogRead(sensitivityPins[i]) / 2048.0 - 1;
|
||||
float x2 = x * x;
|
||||
float x3 = x2 * x;
|
||||
float x4 = x3 * x;
|
||||
float v = (1.0 + x + 0.5 * x2 + 0.166667 * x3) * power[i];
|
||||
axisValues[i] = AXIS_RANGE * (v >= MAX_THRES ? 1 : (v / MAX_THRES));
|
||||
#endif
|
||||
}
|
||||
#ifndef RAW_ANALOG_MODE
|
||||
if (!triggered && maxPower >= HIT_THRES) {
|
||||
triggered = true;
|
||||
digitalWrite(outPins[maxIndex], HIGH);
|
||||
outputValue = (int)(AXIS_RANGE * (maxPower >= MAX_THRES ? 1 : maxPower / MAX_THRES));
|
||||
}
|
||||
|
||||
if (triggered && resetTimer >= RESET_TIME) {
|
||||
triggered = false;
|
||||
resetTimer = 0;
|
||||
digitalWrite(outPins[maxIndex], LOW);
|
||||
maxPower = 0;
|
||||
maxIndex = -1;
|
||||
outputValue = 0;
|
||||
}
|
||||
|
||||
for (byte i = 0; i < CHANNELS; i++) {
|
||||
if (triggered && i == maxIndex) {
|
||||
axisValues[i] = outputValue;
|
||||
} else {
|
||||
axisValues[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (triggered) {
|
||||
resetTimer++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if PLAYER_SELECT == 1
|
||||
Joystick.setXAxis(axisValues[0] > axisValues[1] ? axisValues[0] : -axisValues[1]);
|
||||
Joystick.setYAxis(axisValues[2] > axisValues[3] ? axisValues[2] : -axisValues[3]);
|
||||
Joystick.setRxAxis(0);
|
||||
Joystick.setRyAxis(0);
|
||||
#elif PLAYER_SELECT == 2
|
||||
Joystick.setXAxis(0);
|
||||
Joystick.setYAxis(0);
|
||||
Joystick.setRxAxis(axisValues[0] > axisValues[1] ? axisValues[0] : -axisValues[1]);
|
||||
Joystick.setRyAxis(axisValues[2] > axisValues[3] ? axisValues[2] : -axisValues[3]);
|
||||
#else
|
||||
Joystick.setXAxis(0);
|
||||
Joystick.setYAxis(0);
|
||||
Joystick.setRxAxis(0);
|
||||
Joystick.setRyAxis(0);
|
||||
#endif
|
||||
|
||||
Joystick.sendState();
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
// Enable this mode to pass raw analog data to the game without any post-
|
||||
// processing.
|
||||
// The game has a built-in mechanism to calculate which sensor is triggered
|
||||
// and the force of the hit, so it's recommended to enable this mode.
|
||||
// This also the provides the most similar experience with the arcade.
|
||||
// To disable this mode, remove or comment out this line
|
||||
#define RAW_ANALOG_MODE
|
||||
|
||||
// For MODE_ADJUSTABLE
|
||||
// Select which player this board is. 1 for P1 and 2 for P2.
|
||||
#define PLAYER_SELECT 1
|
||||
|
||||
// For MODE_TWO_PLAYERS
|
||||
// Sensitivity multipliers for each channel, 1.0 as the baseline.
|
||||
#define P1_L_DON_SENS 1.0
|
||||
#define P1_L_KAT_SENS 1.0
|
||||
#define P1_R_DON_SENS 1.0
|
||||
#define P1_R_KAT_SENS 1.0
|
||||
#define P2_L_DON_SENS 1.0
|
||||
#define P2_L_KAT_SENS 1.0
|
||||
#define P2_R_DON_SENS 1.0
|
||||
#define P2_R_KAT_SENS 1.0
|
||||
|
||||
/**********************************************
|
||||
CHANGING THE FOLLOWING PARAMETERS ARE NOT
|
||||
RECOMMENDED UNLESS YOU KNOW HOW THEY WORK
|
||||
***********************************************/
|
||||
|
||||
// Cache length must be the power of 2 (8, 16, 32, etc.).
|
||||
// See cache.h for the reason.
|
||||
#define SAMPLE_CACHE_LENGTH 32
|
||||
|
||||
// The maximum value of a hit (not the minumum value to trigger a heavy hit)
|
||||
// To configure the light and heavy thresholds, do it in the game settings.
|
||||
#define MAX_THRES 5000
|
||||
|
||||
// Input pins for each channel.
|
||||
#define P1_L_DON_IN 4
|
||||
#define P1_L_KAT_IN 5
|
||||
#define P1_R_DON_IN 6
|
||||
#define P1_R_KAT_IN 7
|
||||
|
||||
#define P2_L_DON_IN 8
|
||||
#define P2_L_KAT_IN 1
|
||||
#define P2_R_DON_IN 9
|
||||
#define P2_R_KAT_IN 10
|
||||
|
||||
// Sensitivity adjustment potentiometer input pins.
|
||||
#define P1_L_DON_SENS_IN 15
|
||||
#define P1_L_KAT_SENS_IN 16
|
||||
#define P1_R_DON_SENS_IN 17
|
||||
#define P1_R_KAT_SENS_IN 18
|
||||
|
||||
#define AXIS_RANGE 1023
|
||||
|
||||
#define PLAYERS 2
|
||||
#define CHANNELS 4
|
||||
|
||||
// The minimum value to trigger a light hit.
|
||||
// Disabled if RAW_ANALOG_MODE is on.
|
||||
#define HIT_THRES 1000
|
||||
|
||||
// If the reset time is too short, the game may not be able to
|
||||
// receive the input. From testing I found 40 seems to be the
|
||||
// minimum value so that the game won't miss any hit. If the game
|
||||
// occassionally miss the drum input, increase this value.
|
||||
// Disabled if RAW_ANALOG_MODE is on.
|
||||
#define RESET_TIME 40
|
||||
|
||||
#include <USB.h>
|
||||
#include "joystick.h"
|
||||
#include "cache.h"
|
@ -1,110 +0,0 @@
|
||||
#include "params.h"
|
||||
|
||||
const byte inPins[PLAYERS][CHANNELS] = {
|
||||
P1_L_DON_IN, P1_L_KAT_IN, P1_R_DON_IN, P1_R_KAT_IN,
|
||||
P2_L_DON_IN, P2_L_KAT_IN, P2_R_DON_IN, P2_R_KAT_IN
|
||||
};
|
||||
|
||||
const float sensitivities[PLAYERS][CHANNELS] = {
|
||||
P1_L_DON_SENS, P1_L_KAT_SENS, P1_R_DON_SENS, P1_R_KAT_SENS,
|
||||
P2_L_DON_SENS, P2_L_KAT_SENS, P2_R_DON_SENS, P2_R_KAT_SENS
|
||||
};
|
||||
|
||||
Cache<int, SAMPLE_CACHE_LENGTH> inputWindow[PLAYERS][CHANNELS];
|
||||
unsigned long power[PLAYERS][CHANNELS];
|
||||
|
||||
#ifndef RAW_ANALOG_MODE
|
||||
unsigned long lastPower[PLAYERS][CHANNELS];
|
||||
bool triggered[PLAYERS];
|
||||
unsigned long triggeredTime[PLAYERS][CHANNELS];
|
||||
int outputValue[PLAYERS] = {0, 0};
|
||||
uint resetTimer[PLAYERS] = {0, 0};
|
||||
short maxIndex[PLAYERS] = {0, 0};
|
||||
float maxPower[PLAYERS] = {0, 0};
|
||||
#endif
|
||||
|
||||
uint axisValues[PLAYERS][CHANNELS] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_GAMEPAD, 10, 4,
|
||||
true, true, false, true, true, false,
|
||||
false, false, false, false, false);
|
||||
|
||||
void setup() {
|
||||
for (byte p = 0; p < PLAYERS; p++) {
|
||||
for (byte i = 0; i < CHANNELS; i++) {
|
||||
power[p][i] = 0;
|
||||
#ifndef RAW_ANALOG_MODE
|
||||
lastPower[p][i] = 0;
|
||||
triggered[p] = false;
|
||||
#endif
|
||||
pinMode(inPins[p][i], INPUT);
|
||||
}
|
||||
#ifndef RAW_ANALOG_MODE
|
||||
maxIndex[p] = -1;
|
||||
maxPower[p] = 0;
|
||||
#endif
|
||||
}
|
||||
USB.PID(0x4869);
|
||||
USB.VID(0x4869);
|
||||
USB.productName("Taiko Controller");
|
||||
USB.manufacturerName("GitHub Community");
|
||||
USB.begin();
|
||||
Joystick.begin(false);
|
||||
Joystick.setXAxisRange(-AXIS_RANGE, AXIS_RANGE);
|
||||
Joystick.setYAxisRange(-AXIS_RANGE, AXIS_RANGE);
|
||||
Joystick.setRxAxisRange(-AXIS_RANGE, AXIS_RANGE);
|
||||
Joystick.setRyAxisRange(-AXIS_RANGE, AXIS_RANGE);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
for (byte p = 0; p < PLAYERS; p++) {
|
||||
|
||||
for (byte i = 0; i < CHANNELS; i++) {
|
||||
inputWindow[p][i].put(analogRead(inPins[p][i]));
|
||||
power[p][i] = power[p][i] - inputWindow[p][i].get(1) + inputWindow[p][i].get();
|
||||
#ifndef RAW_ANALOG_MODE
|
||||
if (lastPower[p][i] > maxPower[p] && power[p][i] < lastPower[p][i]) {
|
||||
maxPower[p] = lastPower[p][i];
|
||||
maxIndex[p] = i;
|
||||
}
|
||||
lastPower[p][i] = power[p][i];
|
||||
#else
|
||||
float v = power[p][i] * sensitivities[p][i];
|
||||
axisValues[p][i] = AXIS_RANGE * (v >= MAX_THRES ? 1 : (v / MAX_THRES));
|
||||
#endif
|
||||
}
|
||||
#ifndef RAW_ANALOG_MODE
|
||||
if (!triggered[p] && maxPower[p] >= HIT_THRES) {
|
||||
triggered[p] = true;
|
||||
outputValue[p] = (int)(AXIS_RANGE * (maxPower[p] >= MAX_THRES ? 1 : maxPower[p] / MAX_THRES));
|
||||
}
|
||||
|
||||
if (triggered[p] && resetTimer[p] >= RESET_TIME) {
|
||||
triggered[p] = false;
|
||||
resetTimer[p] = 0;
|
||||
maxPower[p] = 0;
|
||||
maxIndex[p] = -1;
|
||||
outputValue[p] = 0;
|
||||
}
|
||||
|
||||
for (byte i = 0; i < CHANNELS; i++) {
|
||||
if (triggered[p] && i == maxIndex[p]) {
|
||||
axisValues[p][i] = outputValue[p];
|
||||
} else {
|
||||
axisValues[p][i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (triggered[p]) {
|
||||
resetTimer[p]++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Joystick.setXAxis(axisValues[0][0] > axisValues[0][1] ? axisValues[0][0] : -axisValues[0][1]);
|
||||
Joystick.setYAxis(axisValues[0][2] > axisValues[0][3] ? axisValues[0][2] : -axisValues[0][3]);
|
||||
Joystick.setRxAxis(axisValues[1][0] > axisValues[1][1] ? axisValues[1][0] : -axisValues[1][1]);
|
||||
Joystick.setRyAxis(axisValues[1][2] > axisValues[1][3] ? axisValues[1][2] : -axisValues[1][3]);
|
||||
Joystick.sendState();
|
||||
}
|
@ -1,124 +0,0 @@
|
||||
#define CHANNELS 4
|
||||
|
||||
// SAMPLE_CACHE_LENGTH must be power of 2 (8, 16, 32, etc.)
|
||||
// See cache.h for implementation
|
||||
#define SAMPLE_CACHE_LENGTH 32
|
||||
|
||||
// The thresholds are also dependent on SAMPLE_CACHE_LENGTH, if you
|
||||
// changed SAMPLE_CACHE_LENGTH, you should also adjust thresholds
|
||||
#define HIT_THRES 1750
|
||||
#define RESET_THRES 200
|
||||
|
||||
// Sampling period in μs, e.g., 500μs = 0.5ms = 2000Hz
|
||||
#define SAMPLING_PERIOD 500
|
||||
|
||||
// Sensitivity multipliers for each channel, 1.0 as the baseline
|
||||
#define L_DON_SENS 1.0
|
||||
#define L_KAT_SENS 1.0
|
||||
#define R_DON_SENS 1.0
|
||||
#define R_KAT_SENS 1.0
|
||||
|
||||
// Input pins for each channel
|
||||
#define L_DON_IN 4
|
||||
#define L_KAT_IN 5
|
||||
#define R_DON_IN 6
|
||||
#define R_KAT_IN 7
|
||||
|
||||
// Output LED pins for each channel (just for visualization)
|
||||
#define L_DON_LED 10
|
||||
#define L_KAT_LED 11
|
||||
#define R_DON_LED 12
|
||||
#define R_KAT_LED 13
|
||||
|
||||
// Keyboard output for each channel
|
||||
#define L_DON_KEY 'f'
|
||||
#define L_KAT_KEY 'd'
|
||||
#define R_DON_KEY 'j'
|
||||
#define R_KAT_KEY 'k'
|
||||
|
||||
// Enable debug mode to view analog input values from the Serial
|
||||
// Enabling this also disables the keyboard simulation
|
||||
#define DEBUG 0
|
||||
|
||||
#include "USB.h"
|
||||
#include "USBHIDKeyboard.h"
|
||||
#include "cache.h"
|
||||
|
||||
USBHIDKeyboard Keyboard;
|
||||
|
||||
Cache<int, SAMPLE_CACHE_LENGTH> inputWindow[CHANNELS];
|
||||
unsigned long power[CHANNELS];
|
||||
unsigned long lastPower[CHANNELS];
|
||||
|
||||
bool triggered;
|
||||
unsigned long triggeredTime[CHANNELS];
|
||||
|
||||
const byte inPins[] = {L_DON_IN, L_KAT_IN, R_DON_IN, R_KAT_IN};
|
||||
const byte outPins[] = {L_DON_LED, L_KAT_LED, R_DON_LED, R_KAT_LED};
|
||||
const char outKeys[] = {L_DON_KEY, L_KAT_KEY, R_DON_KEY, R_KAT_KEY};
|
||||
float sensitivities[] = {L_DON_SENS, L_KAT_SENS, R_DON_SENS, R_KAT_SENS};
|
||||
|
||||
short maxIndex;
|
||||
float maxPower;
|
||||
|
||||
unsigned long lastTime;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(250000);
|
||||
for (byte i = 0; i < CHANNELS; i++) {
|
||||
power[i] = 0;
|
||||
lastPower[i] = 0;
|
||||
triggered = false;
|
||||
pinMode(inPins[i], INPUT);
|
||||
pinMode(outPins[i], OUTPUT);
|
||||
}
|
||||
maxIndex = -1;
|
||||
maxPower = 0;
|
||||
lastTime = micros();
|
||||
#if !DEBUG
|
||||
Keyboard.begin();
|
||||
USB.begin();
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (maxIndex != -1 && lastPower[maxIndex] < RESET_THRES) {
|
||||
triggered = false;
|
||||
digitalWrite(outPins[maxIndex], LOW);
|
||||
maxIndex = -1;
|
||||
maxPower = 0;
|
||||
}
|
||||
|
||||
for (byte i = 0; i < CHANNELS; i++) {
|
||||
inputWindow[i].put(analogRead(inPins[i]));
|
||||
power[i] = sensitivities[i] *
|
||||
(power[i] - inputWindow[i].get(1) + inputWindow[i].get());
|
||||
|
||||
if (lastPower[i] > maxPower && power[i] < lastPower[i]) {
|
||||
maxPower = lastPower[i];
|
||||
maxIndex = i;
|
||||
}
|
||||
lastPower[i] = power[i];
|
||||
#if DEBUG
|
||||
Serial.print(power[i]);
|
||||
Serial.print(" ");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!triggered && maxPower >= HIT_THRES) {
|
||||
triggered = true;
|
||||
digitalWrite(outPins[maxIndex], HIGH);
|
||||
#if !DEBUG
|
||||
Keyboard.write(outKeys[maxIndex]);
|
||||
#endif
|
||||
}
|
||||
#if DEBUG
|
||||
Serial.print("\n");
|
||||
#endif
|
||||
|
||||
unsigned int frameTime = micros() - lastTime;
|
||||
if (frameTime < SAMPLING_PERIOD) {
|
||||
delayMicroseconds(SAMPLING_PERIOD - frameTime);
|
||||
}
|
||||
lastTime = micros();
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/***************************************************************
|
||||
* *
|
||||
* Taiko Sanro - Arduino *
|
||||
* Cache data structure *
|
||||
* *
|
||||
* Chris *
|
||||
* wisaly@gmail.com *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
#ifndef CACHE_H
|
||||
#define CACHE_H
|
||||
|
||||
template <class T, int L>
|
||||
class Cache {
|
||||
public:
|
||||
Cache() { memset(data_, 0, sizeof(data_)); }
|
||||
inline void put(T value) {
|
||||
current_ = (current_ + 1) & (L - 1);
|
||||
data_[current_] = value;
|
||||
}
|
||||
inline T get(int offset = 0) const {
|
||||
return data_[(current_ + offset) & (L - 1)];
|
||||
}
|
||||
|
||||
private:
|
||||
T data_[L];
|
||||
int current_ = 0;
|
||||
};
|
||||
|
||||
#endif // CACHE_H
|
120
ESP32/ESP32.ino
@ -1,120 +0,0 @@
|
||||
#define CHANNELS 4
|
||||
|
||||
// SAMPLE_CACHE_LENGTH must be power of 2 (8, 16, 32, etc.)
|
||||
// See cache.h for implementation
|
||||
#define SAMPLE_CACHE_LENGTH 16
|
||||
|
||||
// The thresholds are also dependent on SAMPLE_CACHE_LENGTH, if you
|
||||
// changed SAMPLE_CACHE_LENGTH, you should also adjust thresholds
|
||||
#define HIT_THRES 750
|
||||
#define RESET_THRES 200
|
||||
|
||||
// Sampling period in μs, e.g., 500μs = 0.5ms = 2000Hz
|
||||
#define SAMPLING_PERIOD 500
|
||||
|
||||
// Sensitivity multipliers for each channel, 1.0 as the baseline
|
||||
#define L_DON_SENS 1.0
|
||||
#define L_KAT_SENS 1.0
|
||||
#define R_DON_SENS 1.0
|
||||
#define R_KAT_SENS 1.0
|
||||
|
||||
// Input pins for each channel
|
||||
#define L_DON_IN 36
|
||||
#define L_KAT_IN 39
|
||||
#define R_DON_IN 34
|
||||
#define R_KAT_IN 35
|
||||
|
||||
// Output LED pins for each channel (just for visualization)
|
||||
#define L_DON_LED 25
|
||||
#define L_KAT_LED 26
|
||||
#define R_DON_LED 27
|
||||
#define R_KAT_LED 14
|
||||
|
||||
// Keyboard output for each channel
|
||||
#define L_DON_KEY 'f'
|
||||
#define L_KAT_KEY 'd'
|
||||
#define R_DON_KEY 'j'
|
||||
#define R_KAT_KEY 'k'
|
||||
|
||||
// Enable debug mode to view analog input values from the Serial
|
||||
// Enabling this also disables the keyboard simulation
|
||||
#define DEBUG 0
|
||||
|
||||
#include "cache.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
Cache<int, SAMPLE_CACHE_LENGTH> inputWindow[CHANNELS];
|
||||
unsigned long power[CHANNELS];
|
||||
unsigned long lastPower[CHANNELS];
|
||||
|
||||
bool triggered;
|
||||
unsigned long triggeredTime[CHANNELS];
|
||||
|
||||
const byte inPins[] = {L_DON_IN, L_KAT_IN, R_DON_IN, R_KAT_IN};
|
||||
const byte outPins[] = {L_DON_LED, L_KAT_LED, R_DON_LED, R_KAT_LED};
|
||||
const char outKeys[] = {L_DON_KEY, L_KAT_KEY, R_DON_KEY, R_KAT_KEY};
|
||||
float sensitivities[] = {L_DON_SENS, L_KAT_SENS, R_DON_SENS, R_KAT_SENS};
|
||||
|
||||
short maxIndex;
|
||||
float maxPower;
|
||||
|
||||
unsigned long lastTime;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(250000);
|
||||
for (byte i = 0; i < CHANNELS; i++) {
|
||||
power[i] = 0;
|
||||
lastPower[i] = 0;
|
||||
triggered = false;
|
||||
pinMode(inPins[i], INPUT);
|
||||
pinMode(outPins[i], OUTPUT);
|
||||
}
|
||||
maxIndex = -1;
|
||||
maxPower = 0;
|
||||
xTaskCreate(bluetoothTask, "bluetooth", 20000, NULL, 5, NULL);
|
||||
lastTime = micros();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (maxIndex != -1 && lastPower[maxIndex] < RESET_THRES) {
|
||||
triggered = false;
|
||||
digitalWrite(outPins[maxIndex], LOW);
|
||||
maxIndex = -1;
|
||||
maxPower = 0;
|
||||
}
|
||||
|
||||
for (byte i = 0; i < CHANNELS; i++) {
|
||||
inputWindow[i].put(analogRead(inPins[i]));
|
||||
power[i] = sensitivities[i] *
|
||||
(power[i] - inputWindow[i].get(1) + inputWindow[i].get());
|
||||
|
||||
if (lastPower[i] > maxPower && power[i] < lastPower[i]) {
|
||||
maxPower = lastPower[i];
|
||||
maxIndex = i;
|
||||
}
|
||||
lastPower[i] = power[i];
|
||||
#if DEBUG
|
||||
Serial.print(power[i]);
|
||||
Serial.print(" ");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!triggered && maxPower >= HIT_THRES) {
|
||||
triggered = true;
|
||||
digitalWrite(outPins[maxIndex], HIGH);
|
||||
#if !DEBUG
|
||||
if (isBleConnected) {
|
||||
typeChar(outKeys[maxIndex]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if DEBUG
|
||||
Serial.print("\n");
|
||||
#endif
|
||||
|
||||
unsigned int frameTime = micros() - lastTime;
|
||||
if (frameTime < SAMPLING_PERIOD) {
|
||||
delayMicroseconds(SAMPLING_PERIOD - frameTime);
|
||||
}
|
||||
lastTime = micros();
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/***************************************************************
|
||||
* *
|
||||
* Taiko Sanro - Arduino *
|
||||
* Cache data structure *
|
||||
* *
|
||||
* Chris *
|
||||
* wisaly@gmail.com *
|
||||
* *
|
||||
***************************************************************/
|
||||
|
||||
#ifndef CACHE_H
|
||||
#define CACHE_H
|
||||
|
||||
template <class T, int L>
|
||||
class Cache {
|
||||
public:
|
||||
Cache() { memset(data_, 0, sizeof(data_)); }
|
||||
inline void put(T value) {
|
||||
current_ = (current_ + 1) & (L - 1);
|
||||
data_[current_] = value;
|
||||
}
|
||||
inline T get(int offset = 0) const {
|
||||
return data_[(current_ + offset) & (L - 1)];
|
||||
}
|
||||
|
||||
private:
|
||||
T data_[L];
|
||||
int current_ = 0;
|
||||
};
|
||||
|
||||
#endif // CACHE_H
|
232
ESP32/keyboard.h
@ -1,232 +0,0 @@
|
||||
// Bluetooth keyboard implemetation by manuelbl:
|
||||
// https://gist.github.com/manuelbl/66f059effc8a7be148adb1f104666467
|
||||
|
||||
#include "BLEDevice.h"
|
||||
#include "BLEHIDDevice.h"
|
||||
#include "HIDKeyboardTypes.h"
|
||||
#include "HIDTypes.h"
|
||||
|
||||
#define DEVICE_NAME "ESP32 Taiko Controller"
|
||||
|
||||
bool isBleConnected = false;
|
||||
|
||||
// Message (report) sent when a key is pressed or released
|
||||
struct InputReport {
|
||||
uint8_t modifiers; // bitmask: CTRL = 1, SHIFT = 2, ALT = 4
|
||||
uint8_t reserved; // must be 0
|
||||
uint8_t pressedKeys[6]; // up to six concurrenlty pressed keys
|
||||
};
|
||||
|
||||
// Message (report) received when an LED's state changed
|
||||
struct OutputReport {
|
||||
uint8_t leds; // bitmask: num lock = 1, caps lock = 2, scroll lock = 4,
|
||||
// compose = 8, kana = 16
|
||||
};
|
||||
|
||||
// The report map describes the HID device (a keyboard in this case) and
|
||||
// the messages (reports in HID terms) sent and received.
|
||||
static const uint8_t REPORT_MAP[] = {
|
||||
USAGE_PAGE(1),
|
||||
0x01, // Generic Desktop Controls
|
||||
USAGE(1),
|
||||
0x06, // Keyboard
|
||||
COLLECTION(1),
|
||||
0x01, // Application
|
||||
REPORT_ID(1),
|
||||
0x01, // Report ID (1)
|
||||
USAGE_PAGE(1),
|
||||
0x07, // Keyboard/Keypad
|
||||
USAGE_MINIMUM(1),
|
||||
0xE0, // Keyboard Left Control
|
||||
USAGE_MAXIMUM(1),
|
||||
0xE7, // Keyboard Right Control
|
||||
LOGICAL_MINIMUM(1),
|
||||
0x00, // Each bit is either 0 or 1
|
||||
LOGICAL_MAXIMUM(1),
|
||||
0x01,
|
||||
REPORT_COUNT(1),
|
||||
0x08, // 8 bits for the modifier keys
|
||||
REPORT_SIZE(1),
|
||||
0x01,
|
||||
HIDINPUT(1),
|
||||
0x02, // Data, Var, Abs
|
||||
REPORT_COUNT(1),
|
||||
0x01, // 1 byte (unused)
|
||||
REPORT_SIZE(1),
|
||||
0x08,
|
||||
HIDINPUT(1),
|
||||
0x01, // Const, Array, Abs
|
||||
REPORT_COUNT(1),
|
||||
0x06, // 6 bytes (for up to 6 concurrently pressed keys)
|
||||
REPORT_SIZE(1),
|
||||
0x08,
|
||||
LOGICAL_MINIMUM(1),
|
||||
0x00,
|
||||
LOGICAL_MAXIMUM(1),
|
||||
0x65, // 101 keys
|
||||
USAGE_MINIMUM(1),
|
||||
0x00,
|
||||
USAGE_MAXIMUM(1),
|
||||
0x65,
|
||||
HIDINPUT(1),
|
||||
0x00, // Data, Array, Abs
|
||||
REPORT_COUNT(1),
|
||||
0x05, // 5 bits (Num lock, Caps lock, Scroll lock, Compose, Kana)
|
||||
REPORT_SIZE(1),
|
||||
0x01,
|
||||
USAGE_PAGE(1),
|
||||
0x08, // LEDs
|
||||
USAGE_MINIMUM(1),
|
||||
0x01, // Num Lock
|
||||
USAGE_MAXIMUM(1),
|
||||
0x05, // Kana
|
||||
LOGICAL_MINIMUM(1),
|
||||
0x00,
|
||||
LOGICAL_MAXIMUM(1),
|
||||
0x01,
|
||||
HIDOUTPUT(1),
|
||||
0x02, // Data, Var, Abs
|
||||
REPORT_COUNT(1),
|
||||
0x01, // 3 bits (Padding)
|
||||
REPORT_SIZE(1),
|
||||
0x03,
|
||||
HIDOUTPUT(1),
|
||||
0x01, // Const, Array, Abs
|
||||
END_COLLECTION(0) // End application collection
|
||||
};
|
||||
|
||||
BLEHIDDevice* hid;
|
||||
BLECharacteristic* input;
|
||||
BLECharacteristic* output;
|
||||
|
||||
const InputReport NO_KEY_PRESSED = {};
|
||||
|
||||
/*
|
||||
* Callbacks related to BLE connection
|
||||
*/
|
||||
class BleKeyboardCallbacks : public BLEServerCallbacks {
|
||||
void onConnect(BLEServer* server) {
|
||||
isBleConnected = true;
|
||||
|
||||
// Allow notifications for characteristics
|
||||
BLE2902* cccDesc =
|
||||
(BLE2902*)input->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
|
||||
cccDesc->setNotifications(true);
|
||||
|
||||
Serial.println("Client has connected");
|
||||
}
|
||||
|
||||
void onDisconnect(BLEServer* server) {
|
||||
isBleConnected = false;
|
||||
|
||||
// Disallow notifications for characteristics
|
||||
BLE2902* cccDesc =
|
||||
(BLE2902*)input->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
|
||||
cccDesc->setNotifications(false);
|
||||
|
||||
Serial.println("Client has disconnected");
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Called when the client (computer, smart phone) wants to turn on or off
|
||||
* the LEDs in the keyboard.
|
||||
*
|
||||
* bit 0 - NUM LOCK
|
||||
* bit 1 - CAPS LOCK
|
||||
* bit 2 - SCROLL LOCK
|
||||
*/
|
||||
class OutputCallbacks : public BLECharacteristicCallbacks {
|
||||
void onWrite(BLECharacteristic* characteristic) {
|
||||
OutputReport* report = (OutputReport*)characteristic->getData();
|
||||
Serial.print("LED state: ");
|
||||
Serial.print((int)report->leds);
|
||||
Serial.println();
|
||||
}
|
||||
};
|
||||
|
||||
void bluetoothTask(void*) {
|
||||
// initialize the device
|
||||
BLEDevice::init(DEVICE_NAME);
|
||||
BLEServer* server = BLEDevice::createServer();
|
||||
server->setCallbacks(new BleKeyboardCallbacks());
|
||||
|
||||
// create an HID device
|
||||
hid = new BLEHIDDevice(server);
|
||||
input = hid->inputReport(1); // report ID
|
||||
output = hid->outputReport(1); // report ID
|
||||
output->setCallbacks(new OutputCallbacks());
|
||||
|
||||
// set manufacturer name
|
||||
hid->manufacturer()->setValue("Maker Community");
|
||||
// set USB vendor and product ID
|
||||
hid->pnp(0x02, 0xe502, 0xa111, 0x0210);
|
||||
// information about HID device: device is not localized, device can be
|
||||
// connected
|
||||
hid->hidInfo(0x00, 0x02);
|
||||
|
||||
// Security: device requires bonding
|
||||
BLESecurity* security = new BLESecurity();
|
||||
security->setAuthenticationMode(ESP_LE_AUTH_BOND);
|
||||
|
||||
// set report map
|
||||
hid->reportMap((uint8_t*)REPORT_MAP, sizeof(REPORT_MAP));
|
||||
hid->startServices();
|
||||
|
||||
// set battery level to 100%
|
||||
hid->setBatteryLevel(100);
|
||||
|
||||
// advertise the services
|
||||
BLEAdvertising* advertising = server->getAdvertising();
|
||||
advertising->setAppearance(HID_KEYBOARD);
|
||||
advertising->addServiceUUID(hid->hidService()->getUUID());
|
||||
advertising->addServiceUUID(hid->deviceInfo()->getUUID());
|
||||
advertising->addServiceUUID(hid->batteryService()->getUUID());
|
||||
advertising->start();
|
||||
|
||||
Serial.println("BLE ready");
|
||||
delay(portMAX_DELAY);
|
||||
};
|
||||
|
||||
void typeText(const char* text) {
|
||||
int len = strlen(text);
|
||||
for (int i = 0; i < len; i++) {
|
||||
// translate character to key combination
|
||||
uint8_t val = (uint8_t)text[i];
|
||||
if (val > KEYMAP_SIZE)
|
||||
continue; // character not available on keyboard - skip
|
||||
KEYMAP map = keymap[val];
|
||||
|
||||
// create input report
|
||||
InputReport report = {.modifiers = map.modifier,
|
||||
.reserved = 0,
|
||||
.pressedKeys = {map.usage, 0, 0, 0, 0, 0}};
|
||||
|
||||
// send the input report
|
||||
input->setValue((uint8_t*)&report, sizeof(report));
|
||||
input->notify();
|
||||
|
||||
delay(5);
|
||||
|
||||
// release all keys between two characters; otherwise two identical
|
||||
// consecutive characters are treated as just one key press
|
||||
input->setValue((uint8_t*)&NO_KEY_PRESSED, sizeof(NO_KEY_PRESSED));
|
||||
input->notify();
|
||||
|
||||
delay(5);
|
||||
}
|
||||
}
|
||||
|
||||
void typeChar(char c) {
|
||||
uint8_t val = (uint8_t)c;
|
||||
KEYMAP map = keymap[val];
|
||||
InputReport report = {.modifiers = map.modifier,
|
||||
.reserved = 0,
|
||||
.pressedKeys = {map.usage, 0, 0, 0, 0, 0}};
|
||||
input->setValue((uint8_t*)&report, sizeof(report));
|
||||
input->notify();
|
||||
delay(1);
|
||||
input->setValue((uint8_t*)&NO_KEY_PRESSED, sizeof(NO_KEY_PRESSED));
|
||||
input->notify();
|
||||
delay(1);
|
||||
}
|
110
Firmware/Firmware.ino
Normal file
@ -0,0 +1,110 @@
|
||||
/****************************************************
|
||||
IF YOU WANT TO CHANGE THE SETTINGS GO TO params.h !
|
||||
*****************************************************/
|
||||
#include <FastLED.h>
|
||||
#include "params.h"
|
||||
|
||||
CRGB player_led[1];
|
||||
|
||||
const byte inPins[CHANNELS] = {
|
||||
L_DON_IN, L_KAT_IN, R_DON_IN, R_KAT_IN};
|
||||
const byte sensitivityPins[CHANNELS] = {
|
||||
L_DON_ADJUST, L_KAT_ADJUST, R_DON_ADJUST, R_KAT_ADJUST};
|
||||
|
||||
const byte ledPins[CHANNELS] = {
|
||||
L_DON_LED, L_KAT_LED, R_DON_LED, R_KAT_LED};
|
||||
|
||||
Cache<int, SAMPLE_CACHE_LENGTH> inputWindow[CHANNELS];
|
||||
unsigned long power[CHANNELS];
|
||||
|
||||
uint axisValues[CHANNELS] = {0, 0, 0, 0};
|
||||
|
||||
Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, JOYSTICK_TYPE_GAMEPAD, 10, 4, true, true, false, true, true, false, false, false, false, false, false);
|
||||
|
||||
// ===================================================================================================
|
||||
void setup()
|
||||
{
|
||||
#if DEBUG
|
||||
Serial.begin(250000);
|
||||
#endif
|
||||
|
||||
// Setting the internal ESP32 RGB LED to the player's color :
|
||||
// Red for player 1, Blue for player 2.
|
||||
FastLED.addLeds<NEOPIXEL, 48>(player_led, 1); // gpio48
|
||||
player_led[0] = PLAYER_SELECT == 1 ? CRGB::Red : CRGB::Aqua;
|
||||
FastLED.show();
|
||||
|
||||
for (byte i = 0; i < CHANNELS; i++)
|
||||
{ // Set pin mode for all input, sensitivity; and LED pins.
|
||||
pinMode(inPins[i], INPUT);
|
||||
pinMode(sensitivityPins[i], INPUT);
|
||||
pinMode(ledPins[i], OUTPUT);
|
||||
|
||||
ledcSetup(i, ledFreq, ledResolution); // Init all ledc channels.
|
||||
ledcAttachPin(ledPins[i], i); // Attach each LEDs to a different ledc pwm channel.
|
||||
|
||||
// Then init the array(s) which will hold the piezzos values on each cycle.
|
||||
power[i] = 0;
|
||||
}
|
||||
|
||||
// Init USB
|
||||
USB.PID(0x4869);
|
||||
USB.VID(0x4869);
|
||||
USB.productName("Nijiiro Analog IO Board");
|
||||
USB.manufacturerName("ShikyC, AkaiiKitsune");
|
||||
|
||||
USB.begin();
|
||||
|
||||
// Init Joystick
|
||||
Joystick.begin(false);
|
||||
Joystick.setXAxisRange(-AXIS_RANGE, AXIS_RANGE);
|
||||
Joystick.setYAxisRange(-AXIS_RANGE, AXIS_RANGE);
|
||||
Joystick.setRxAxisRange(-AXIS_RANGE, AXIS_RANGE);
|
||||
Joystick.setRyAxisRange(-AXIS_RANGE, AXIS_RANGE);
|
||||
}
|
||||
|
||||
// ===================================================================================================
|
||||
void loop()
|
||||
{
|
||||
for (byte i = 0; i < CHANNELS; i++)
|
||||
{
|
||||
inputWindow[i].put(analogRead(inPins[i]));
|
||||
power[i] = power[i] - inputWindow[i].get(1) + inputWindow[i].get();
|
||||
|
||||
float x = analogRead(sensitivityPins[i]) / 2048.0 - 1;
|
||||
float x2 = x * x;
|
||||
float x3 = x2 * x;
|
||||
float x4 = x3 * x;
|
||||
float v = (1.0 + x + 0.5 * x2 + 0.166667 * x3) * power[i];
|
||||
axisValues[i] = AXIS_RANGE * (v >= MAX_THRES ? 1 : (v / MAX_THRES));
|
||||
|
||||
#if DEBUG
|
||||
Serial.print("Channel_" + String(i) + ":");
|
||||
if (i < CHANNELS - 1)
|
||||
Serial.print(power[i] + ",");
|
||||
else
|
||||
Serial.println(power[i]);
|
||||
#endif
|
||||
|
||||
ledcWrite(i, (int)((axisValues[i] / AXIS_RANGE) * 255));
|
||||
}
|
||||
|
||||
#if PLAYER_SELECT == 1
|
||||
Joystick.setXAxis(axisValues[0] > axisValues[1] ? axisValues[0] : -axisValues[1]);
|
||||
Joystick.setYAxis(axisValues[2] > axisValues[3] ? axisValues[2] : -axisValues[3]);
|
||||
Joystick.setRxAxis(0);
|
||||
Joystick.setRyAxis(0);
|
||||
#elif PLAYER_SELECT == 2
|
||||
Joystick.setXAxis(0);
|
||||
Joystick.setYAxis(0);
|
||||
Joystick.setRxAxis(axisValues[0] > axisValues[1] ? axisValues[0] : -axisValues[1]);
|
||||
Joystick.setRyAxis(axisValues[2] > axisValues[3] ? axisValues[2] : -axisValues[3]);
|
||||
#else
|
||||
Joystick.setXAxis(0);
|
||||
Joystick.setYAxis(0);
|
||||
Joystick.setRxAxis(0);
|
||||
Joystick.setRyAxis(0);
|
||||
#endif
|
||||
|
||||
Joystick.sendState();
|
||||
}
|
50
Firmware/params.h
Normal file
@ -0,0 +1,50 @@
|
||||
// Select which player this board is. 1 for P1 and 2 for P2.
|
||||
#define PLAYER_SELECT 1
|
||||
|
||||
// Enable debug mode to view analog input values from Serial.
|
||||
// Make sure to use the serial plotter and not the serial monitor!
|
||||
#define DEBUG 0
|
||||
|
||||
/**********************************************
|
||||
EVERYTHING BEYOND THIS POINT DOESN'T NEED TO
|
||||
BE EDITED EXCEPT IF YOU MODIFIED THE PCB !
|
||||
***********************************************/
|
||||
// ============ PIN DEFINITION ================
|
||||
// Input pins.
|
||||
#define L_KAT_IN 4
|
||||
#define L_DON_IN 5
|
||||
#define R_DON_IN 6
|
||||
#define R_KAT_IN 7
|
||||
|
||||
// Sensitivity adjustment potentiometer input pins.
|
||||
#define L_KAT_ADJUST 9
|
||||
#define L_DON_ADJUST 10
|
||||
#define R_DON_ADJUST 11
|
||||
#define R_KAT_ADJUST 12
|
||||
|
||||
// LED pins.
|
||||
#define L_KAT_LED 17
|
||||
#define L_DON_LED 18
|
||||
#define R_DON_LED 8
|
||||
#define R_KAT_LED 3
|
||||
|
||||
// ============ OTHER SETTINGS ================
|
||||
// The maximum value of a hit (not the minumum value to trigger a heavy hit)
|
||||
// To configure the light and heavy thresholds, do it in the game settings.
|
||||
#define MAX_THRES 5000
|
||||
|
||||
// LED PWM Settings.
|
||||
#define ledFreq 1000
|
||||
#define ledResolution 8
|
||||
|
||||
// Sampling Cache, a higher value means a smoother signal. 32 is a good value for the esp32.
|
||||
// This value must be a power of 2 (4, 8, 16, 32, etc).
|
||||
#define SAMPLE_CACHE_LENGTH 32
|
||||
|
||||
#define AXIS_RANGE 1023
|
||||
#define PLAYERS 2
|
||||
#define CHANNELS 4
|
||||
|
||||
#include <USB.h>
|
||||
#include "joystick.h"
|
||||
#include "cache.h"
|
BIN
Images/banner-taiko.png
Normal file
After Width: | Height: | Size: 237 KiB |
BIN
Images/bootleg_cab.png
Normal file
After Width: | Height: | Size: 2.5 MiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
5097
PCB/Export/Taiko IoBoard-B_Cu.gbl
Normal file
128
PCB/Export/Taiko IoBoard-B_Mask.gbs
Normal file
@ -0,0 +1,128 @@
|
||||
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,8.0.1*
|
||||
G04 #@! TF.CreationDate,2024-04-30T12:08:52+02:00*
|
||||
G04 #@! TF.ProjectId,Taiko IoBoard,5461696b-6f20-4496-9f42-6f6172642e6b,1*
|
||||
G04 #@! TF.SameCoordinates,Original*
|
||||
G04 #@! TF.FileFunction,Soldermask,Bot*
|
||||
G04 #@! TF.FilePolarity,Negative*
|
||||
%FSLAX46Y46*%
|
||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Created by KiCad (PCBNEW 8.0.1) date 2024-04-30 12:08:52*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
G04 Aperture macros list*
|
||||
%AMRoundRect*
|
||||
0 Rectangle with rounded corners*
|
||||
0 $1 Rounding radius*
|
||||
0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners*
|
||||
0 Add a 4 corners polygon primitive as box body*
|
||||
4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0*
|
||||
0 Add four circle primitives for the rounded corners*
|
||||
1,1,$1+$1,$2,$3*
|
||||
1,1,$1+$1,$4,$5*
|
||||
1,1,$1+$1,$6,$7*
|
||||
1,1,$1+$1,$8,$9*
|
||||
0 Add four rect primitives between the rounded corners*
|
||||
20,1,$1+$1,$2,$3,$4,$5,0*
|
||||
20,1,$1+$1,$4,$5,$6,$7,0*
|
||||
20,1,$1+$1,$6,$7,$8,$9,0*
|
||||
20,1,$1+$1,$8,$9,$2,$3,0*%
|
||||
G04 Aperture macros list end*
|
||||
%ADD10R,2.000000X1.200000*%
|
||||
%ADD11O,2.000000X1.200000*%
|
||||
%ADD12RoundRect,0.300000X0.600000X-0.300000X0.600000X0.300000X-0.600000X0.300000X-0.600000X-0.300000X0*%
|
||||
%ADD13O,1.800000X1.200000*%
|
||||
%ADD14C,1.900000*%
|
||||
%ADD15C,3.800000*%
|
||||
%ADD16C,0.600000*%
|
||||
G04 APERTURE END LIST*
|
||||
D10*
|
||||
X72350000Y-32554351D03*
|
||||
D11*
|
||||
X72350000Y-35094351D03*
|
||||
X72350000Y-37634351D03*
|
||||
X72350000Y-40174351D03*
|
||||
X72350000Y-42714351D03*
|
||||
X72350000Y-45254351D03*
|
||||
X72350000Y-47794351D03*
|
||||
X72350000Y-50334351D03*
|
||||
X72350000Y-52874351D03*
|
||||
X72350000Y-55414351D03*
|
||||
X72350000Y-57954351D03*
|
||||
X72350000Y-60494351D03*
|
||||
X72350000Y-63034351D03*
|
||||
X72350000Y-65574351D03*
|
||||
X72350000Y-68114351D03*
|
||||
X72350000Y-70654351D03*
|
||||
X72350000Y-73194351D03*
|
||||
X72350000Y-75734351D03*
|
||||
X72350000Y-78274351D03*
|
||||
X72346320Y-80811631D03*
|
||||
X72346320Y-83351631D03*
|
||||
X72346320Y-85891631D03*
|
||||
X95210000Y-85894351D03*
|
||||
X95210000Y-83354351D03*
|
||||
X95210000Y-80814351D03*
|
||||
X95210000Y-78274351D03*
|
||||
X95210000Y-75734351D03*
|
||||
X95210000Y-73194351D03*
|
||||
X95210000Y-70654351D03*
|
||||
X95210000Y-68114351D03*
|
||||
X95210000Y-65574351D03*
|
||||
X95210000Y-63034351D03*
|
||||
X95210000Y-60494351D03*
|
||||
X95210000Y-57954351D03*
|
||||
X95210000Y-55414351D03*
|
||||
X95210000Y-52874351D03*
|
||||
X95210000Y-50334351D03*
|
||||
X95210000Y-47794351D03*
|
||||
X95210000Y-45254351D03*
|
||||
X95210000Y-42714351D03*
|
||||
X95210000Y-40174351D03*
|
||||
X95210000Y-37634351D03*
|
||||
X95210000Y-35094351D03*
|
||||
X95210000Y-32554351D03*
|
||||
D12*
|
||||
X126207290Y-36454803D03*
|
||||
D13*
|
||||
X126207290Y-34454803D03*
|
||||
D14*
|
||||
X103760000Y-90381262D03*
|
||||
X101220000Y-87841262D03*
|
||||
X103760000Y-85301262D03*
|
||||
D12*
|
||||
X126207290Y-71257666D03*
|
||||
D13*
|
||||
X126207290Y-69257666D03*
|
||||
D14*
|
||||
X103760000Y-55419726D03*
|
||||
X101220000Y-52879726D03*
|
||||
X103760000Y-50339726D03*
|
||||
X104170000Y-38056262D03*
|
||||
X101630000Y-35516262D03*
|
||||
X104170000Y-32976262D03*
|
||||
D12*
|
||||
X126207290Y-88779803D03*
|
||||
D13*
|
||||
X126207290Y-86779803D03*
|
||||
D15*
|
||||
X71350000Y-28054351D03*
|
||||
D12*
|
||||
X126207290Y-53799517D03*
|
||||
D13*
|
||||
X126207290Y-51799517D03*
|
||||
D15*
|
||||
X117600000Y-95054351D03*
|
||||
D14*
|
||||
X103760000Y-72859125D03*
|
||||
X101220000Y-70319125D03*
|
||||
X103760000Y-67779125D03*
|
||||
D15*
|
||||
X117600000Y-28054351D03*
|
||||
D16*
|
||||
X121100000Y-30134637D03*
|
||||
X121100000Y-47529351D03*
|
||||
X121100000Y-65000000D03*
|
||||
X121100000Y-82534637D03*
|
||||
M02*
|
15
PCB/Export/Taiko IoBoard-B_Paste.gbp
Normal file
@ -0,0 +1,15 @@
|
||||
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,8.0.1*
|
||||
G04 #@! TF.CreationDate,2024-04-30T12:08:52+02:00*
|
||||
G04 #@! TF.ProjectId,Taiko IoBoard,5461696b-6f20-4496-9f42-6f6172642e6b,1*
|
||||
G04 #@! TF.SameCoordinates,Original*
|
||||
G04 #@! TF.FileFunction,Paste,Bot*
|
||||
G04 #@! TF.FilePolarity,Positive*
|
||||
%FSLAX46Y46*%
|
||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Created by KiCad (PCBNEW 8.0.1) date 2024-04-30 12:08:52*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
G04 APERTURE END LIST*
|
||||
M02*
|
3235
PCB/Export/Taiko IoBoard-B_Silkscreen.gbo
Normal file
23
PCB/Export/Taiko IoBoard-Edge_Cuts.gm1
Normal file
@ -0,0 +1,23 @@
|
||||
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,8.0.1*
|
||||
G04 #@! TF.CreationDate,2024-04-30T12:08:52+02:00*
|
||||
G04 #@! TF.ProjectId,Taiko IoBoard,5461696b-6f20-4496-9f42-6f6172642e6b,1*
|
||||
G04 #@! TF.SameCoordinates,Original*
|
||||
G04 #@! TF.FileFunction,Profile,NP*
|
||||
%FSLAX46Y46*%
|
||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Created by KiCad (PCBNEW 8.0.1) date 2024-04-30 12:08:52*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
G04 #@! TA.AperFunction,Profile*
|
||||
%ADD10C,0.050000*%
|
||||
G04 #@! TD*
|
||||
G04 APERTURE END LIST*
|
||||
D10*
|
||||
X68349999Y-25049509D02*
|
||||
X133850000Y-25049509D01*
|
||||
X133850000Y-97807983D01*
|
||||
X68349999Y-97807983D01*
|
||||
X68349999Y-25049509D01*
|
||||
M02*
|
7682
PCB/Export/Taiko IoBoard-F_Cu.gtl
Normal file
197
PCB/Export/Taiko IoBoard-F_Mask.gts
Normal file
@ -0,0 +1,197 @@
|
||||
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,8.0.1*
|
||||
G04 #@! TF.CreationDate,2024-04-30T12:08:52+02:00*
|
||||
G04 #@! TF.ProjectId,Taiko IoBoard,5461696b-6f20-4496-9f42-6f6172642e6b,1*
|
||||
G04 #@! TF.SameCoordinates,Original*
|
||||
G04 #@! TF.FileFunction,Soldermask,Top*
|
||||
G04 #@! TF.FilePolarity,Negative*
|
||||
%FSLAX46Y46*%
|
||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Created by KiCad (PCBNEW 8.0.1) date 2024-04-30 12:08:52*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
G04 Aperture macros list*
|
||||
%AMRoundRect*
|
||||
0 Rectangle with rounded corners*
|
||||
0 $1 Rounding radius*
|
||||
0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners*
|
||||
0 Add a 4 corners polygon primitive as box body*
|
||||
4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0*
|
||||
0 Add four circle primitives for the rounded corners*
|
||||
1,1,$1+$1,$2,$3*
|
||||
1,1,$1+$1,$4,$5*
|
||||
1,1,$1+$1,$6,$7*
|
||||
1,1,$1+$1,$8,$9*
|
||||
0 Add four rect primitives between the rounded corners*
|
||||
20,1,$1+$1,$2,$3,$4,$5,0*
|
||||
20,1,$1+$1,$4,$5,$6,$7,0*
|
||||
20,1,$1+$1,$6,$7,$8,$9,0*
|
||||
20,1,$1+$1,$8,$9,$2,$3,0*%
|
||||
G04 Aperture macros list end*
|
||||
%ADD10RoundRect,0.250000X0.625000X-0.400000X0.625000X0.400000X-0.625000X0.400000X-0.625000X-0.400000X0*%
|
||||
%ADD11R,2.500000X1.524000*%
|
||||
%ADD12R,2.000000X1.200000*%
|
||||
%ADD13O,2.000000X1.200000*%
|
||||
%ADD14RoundRect,0.250000X-0.400000X-0.625000X0.400000X-0.625000X0.400000X0.625000X-0.400000X0.625000X0*%
|
||||
%ADD15RoundRect,0.250001X0.462499X0.624999X-0.462499X0.624999X-0.462499X-0.624999X0.462499X-0.624999X0*%
|
||||
%ADD16RoundRect,0.300000X0.600000X-0.300000X0.600000X0.300000X-0.600000X0.300000X-0.600000X-0.300000X0*%
|
||||
%ADD17O,1.800000X1.200000*%
|
||||
%ADD18C,1.900000*%
|
||||
%ADD19C,3.800000*%
|
||||
%ADD20C,0.600000*%
|
||||
G04 APERTURE END LIST*
|
||||
D10*
|
||||
X110350000Y-91959637D03*
|
||||
X110350000Y-88859637D03*
|
||||
D11*
|
||||
X121850000Y-90359637D03*
|
||||
X121850000Y-85209637D03*
|
||||
X113350000Y-85209637D03*
|
||||
X113350000Y-90359637D03*
|
||||
D12*
|
||||
X72350000Y-32554351D03*
|
||||
D13*
|
||||
X72350000Y-35094351D03*
|
||||
X72350000Y-37634351D03*
|
||||
X72350000Y-40174351D03*
|
||||
X72350000Y-42714351D03*
|
||||
X72350000Y-45254351D03*
|
||||
X72350000Y-47794351D03*
|
||||
X72350000Y-50334351D03*
|
||||
X72350000Y-52874351D03*
|
||||
X72350000Y-55414351D03*
|
||||
X72350000Y-57954351D03*
|
||||
X72350000Y-60494351D03*
|
||||
X72350000Y-63034351D03*
|
||||
X72350000Y-65574351D03*
|
||||
X72350000Y-68114351D03*
|
||||
X72350000Y-70654351D03*
|
||||
X72350000Y-73194351D03*
|
||||
X72350000Y-75734351D03*
|
||||
X72350000Y-78274351D03*
|
||||
X72346320Y-80811631D03*
|
||||
X72346320Y-83351631D03*
|
||||
X72346320Y-85891631D03*
|
||||
X95210000Y-85894351D03*
|
||||
X95210000Y-83354351D03*
|
||||
X95210000Y-80814351D03*
|
||||
X95210000Y-78274351D03*
|
||||
X95210000Y-75734351D03*
|
||||
X95210000Y-73194351D03*
|
||||
X95210000Y-70654351D03*
|
||||
X95210000Y-68114351D03*
|
||||
X95210000Y-65574351D03*
|
||||
X95210000Y-63034351D03*
|
||||
X95210000Y-60494351D03*
|
||||
X95210000Y-57954351D03*
|
||||
X95210000Y-55414351D03*
|
||||
X95210000Y-52874351D03*
|
||||
X95210000Y-50334351D03*
|
||||
X95210000Y-47794351D03*
|
||||
X95210000Y-45254351D03*
|
||||
X95210000Y-42714351D03*
|
||||
X95210000Y-40174351D03*
|
||||
X95210000Y-37634351D03*
|
||||
X95210000Y-35094351D03*
|
||||
X95210000Y-32554351D03*
|
||||
D14*
|
||||
X122612500Y-82534637D03*
|
||||
X125712500Y-82534637D03*
|
||||
X122612500Y-30134637D03*
|
||||
X125712500Y-30134637D03*
|
||||
D10*
|
||||
X110350000Y-56941851D03*
|
||||
X110350000Y-53841851D03*
|
||||
D15*
|
||||
X131587500Y-47529351D03*
|
||||
X128612500Y-47529351D03*
|
||||
D16*
|
||||
X126207290Y-36454803D03*
|
||||
D17*
|
||||
X126207290Y-34454803D03*
|
||||
D18*
|
||||
X103760000Y-90381262D03*
|
||||
X101220000Y-87841262D03*
|
||||
X103760000Y-85301262D03*
|
||||
D16*
|
||||
X126207290Y-71257666D03*
|
||||
D17*
|
||||
X126207290Y-69257666D03*
|
||||
D18*
|
||||
X103760000Y-55419726D03*
|
||||
X101220000Y-52879726D03*
|
||||
X103760000Y-50339726D03*
|
||||
X104170000Y-38056262D03*
|
||||
X101630000Y-35516262D03*
|
||||
X104170000Y-32976262D03*
|
||||
D10*
|
||||
X110350000Y-51766851D03*
|
||||
X110350000Y-48666851D03*
|
||||
D11*
|
||||
X121850000Y-72837500D03*
|
||||
X121850000Y-67687500D03*
|
||||
X113350000Y-67687500D03*
|
||||
X113350000Y-72837500D03*
|
||||
X121850000Y-38034637D03*
|
||||
X121850000Y-32884637D03*
|
||||
X113350000Y-32884637D03*
|
||||
X113350000Y-38034637D03*
|
||||
D10*
|
||||
X110350000Y-86709637D03*
|
||||
X110350000Y-83609637D03*
|
||||
D16*
|
||||
X126207290Y-88779803D03*
|
||||
D17*
|
||||
X126207290Y-86779803D03*
|
||||
D15*
|
||||
X131587500Y-82534637D03*
|
||||
X128612500Y-82534637D03*
|
||||
D19*
|
||||
X71350000Y-28054351D03*
|
||||
D16*
|
||||
X126207290Y-53799517D03*
|
||||
D17*
|
||||
X126207290Y-51799517D03*
|
||||
D10*
|
||||
X110350000Y-74437500D03*
|
||||
X110350000Y-71337500D03*
|
||||
D15*
|
||||
X131587500Y-65000000D03*
|
||||
X128612500Y-65000000D03*
|
||||
D10*
|
||||
X110350000Y-69187500D03*
|
||||
X110350000Y-66087500D03*
|
||||
D15*
|
||||
X131587500Y-30134637D03*
|
||||
X128612500Y-30134637D03*
|
||||
D19*
|
||||
X117600000Y-95054351D03*
|
||||
D10*
|
||||
X110350000Y-34384637D03*
|
||||
X110350000Y-31284637D03*
|
||||
D14*
|
||||
X122612500Y-65000000D03*
|
||||
X125712500Y-65000000D03*
|
||||
X122612500Y-47529351D03*
|
||||
X125712500Y-47529351D03*
|
||||
D18*
|
||||
X103760000Y-72859125D03*
|
||||
X101220000Y-70319125D03*
|
||||
X103760000Y-67779125D03*
|
||||
D11*
|
||||
X121850000Y-55379351D03*
|
||||
X121850000Y-50229351D03*
|
||||
X113350000Y-50229351D03*
|
||||
X113350000Y-55379351D03*
|
||||
D19*
|
||||
X117600000Y-28054351D03*
|
||||
D10*
|
||||
X110350000Y-39634637D03*
|
||||
X110350000Y-36534637D03*
|
||||
D20*
|
||||
X121100000Y-30134637D03*
|
||||
X121100000Y-47529351D03*
|
||||
X121100000Y-65000000D03*
|
||||
X121100000Y-82534637D03*
|
||||
M02*
|
102
PCB/Export/Taiko IoBoard-F_Paste.gtp
Normal file
@ -0,0 +1,102 @@
|
||||
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,8.0.1*
|
||||
G04 #@! TF.CreationDate,2024-04-30T12:08:52+02:00*
|
||||
G04 #@! TF.ProjectId,Taiko IoBoard,5461696b-6f20-4496-9f42-6f6172642e6b,1*
|
||||
G04 #@! TF.SameCoordinates,Original*
|
||||
G04 #@! TF.FileFunction,Paste,Top*
|
||||
G04 #@! TF.FilePolarity,Positive*
|
||||
%FSLAX46Y46*%
|
||||
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Created by KiCad (PCBNEW 8.0.1) date 2024-04-30 12:08:52*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
G04 Aperture macros list*
|
||||
%AMRoundRect*
|
||||
0 Rectangle with rounded corners*
|
||||
0 $1 Rounding radius*
|
||||
0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners*
|
||||
0 Add a 4 corners polygon primitive as box body*
|
||||
4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0*
|
||||
0 Add four circle primitives for the rounded corners*
|
||||
1,1,$1+$1,$2,$3*
|
||||
1,1,$1+$1,$4,$5*
|
||||
1,1,$1+$1,$6,$7*
|
||||
1,1,$1+$1,$8,$9*
|
||||
0 Add four rect primitives between the rounded corners*
|
||||
20,1,$1+$1,$2,$3,$4,$5,0*
|
||||
20,1,$1+$1,$4,$5,$6,$7,0*
|
||||
20,1,$1+$1,$6,$7,$8,$9,0*
|
||||
20,1,$1+$1,$8,$9,$2,$3,0*%
|
||||
G04 Aperture macros list end*
|
||||
%ADD10RoundRect,0.250000X0.625000X-0.400000X0.625000X0.400000X-0.625000X0.400000X-0.625000X-0.400000X0*%
|
||||
%ADD11R,2.500000X1.524000*%
|
||||
%ADD12RoundRect,0.250000X-0.400000X-0.625000X0.400000X-0.625000X0.400000X0.625000X-0.400000X0.625000X0*%
|
||||
%ADD13RoundRect,0.250001X0.462499X0.624999X-0.462499X0.624999X-0.462499X-0.624999X0.462499X-0.624999X0*%
|
||||
G04 APERTURE END LIST*
|
||||
D10*
|
||||
X110350000Y-91959637D03*
|
||||
X110350000Y-88859637D03*
|
||||
D11*
|
||||
X121850000Y-90359637D03*
|
||||
X121850000Y-85209637D03*
|
||||
X113350000Y-85209637D03*
|
||||
X113350000Y-90359637D03*
|
||||
D12*
|
||||
X122612500Y-82534637D03*
|
||||
X125712500Y-82534637D03*
|
||||
X122612500Y-30134637D03*
|
||||
X125712500Y-30134637D03*
|
||||
D10*
|
||||
X110350000Y-56941851D03*
|
||||
X110350000Y-53841851D03*
|
||||
D13*
|
||||
X131587500Y-47529351D03*
|
||||
X128612500Y-47529351D03*
|
||||
D10*
|
||||
X110350000Y-51766851D03*
|
||||
X110350000Y-48666851D03*
|
||||
D11*
|
||||
X121850000Y-72837500D03*
|
||||
X121850000Y-67687500D03*
|
||||
X113350000Y-67687500D03*
|
||||
X113350000Y-72837500D03*
|
||||
X121850000Y-38034637D03*
|
||||
X121850000Y-32884637D03*
|
||||
X113350000Y-32884637D03*
|
||||
X113350000Y-38034637D03*
|
||||
D10*
|
||||
X110350000Y-86709637D03*
|
||||
X110350000Y-83609637D03*
|
||||
D13*
|
||||
X131587500Y-82534637D03*
|
||||
X128612500Y-82534637D03*
|
||||
D10*
|
||||
X110350000Y-74437500D03*
|
||||
X110350000Y-71337500D03*
|
||||
D13*
|
||||
X131587500Y-65000000D03*
|
||||
X128612500Y-65000000D03*
|
||||
D10*
|
||||
X110350000Y-69187500D03*
|
||||
X110350000Y-66087500D03*
|
||||
D13*
|
||||
X131587500Y-30134637D03*
|
||||
X128612500Y-30134637D03*
|
||||
D10*
|
||||
X110350000Y-34384637D03*
|
||||
X110350000Y-31284637D03*
|
||||
D12*
|
||||
X122612500Y-65000000D03*
|
||||
X125712500Y-65000000D03*
|
||||
X122612500Y-47529351D03*
|
||||
X125712500Y-47529351D03*
|
||||
D11*
|
||||
X121850000Y-55379351D03*
|
||||
X121850000Y-50229351D03*
|
||||
X113350000Y-50229351D03*
|
||||
X113350000Y-55379351D03*
|
||||
D10*
|
||||
X110350000Y-39634637D03*
|
||||
X110350000Y-36534637D03*
|
||||
M02*
|
11029
PCB/Export/Taiko IoBoard-F_Silkscreen.gto
Normal file
162
PCB/Export/Taiko IoBoard-NPTH-drl_map.gbr
Normal file
@ -0,0 +1,162 @@
|
||||
%TF.GenerationSoftware,KiCad,Pcbnew,8.0.1*%
|
||||
%TF.CreationDate,2024-04-30T12:08:59+02:00*%
|
||||
%TF.ProjectId,Taiko IoBoard,5461696b-6f20-4496-9f42-6f6172642e6b,1*%
|
||||
%TF.SameCoordinates,Original*%
|
||||
%TF.FileFunction,Drillmap*%
|
||||
%TF.FilePolarity,Positive*%
|
||||
%FSLAX45Y45*%
|
||||
G04 Gerber Fmt 4.5, Leading zero omitted, Abs format (unit mm)*
|
||||
G04 Created by KiCad (PCBNEW 8.0.1) date 2024-04-30 12:08:59*
|
||||
%MOMM*%
|
||||
%LPD*%
|
||||
G01*
|
||||
G04 APERTURE LIST*
|
||||
%ADD10C,0.050000*%
|
||||
%ADD11C,0.200000*%
|
||||
G04 APERTURE END LIST*
|
||||
D10*
|
||||
X6835000Y-2504951D02*
|
||||
X13385000Y-2504951D01*
|
||||
X13385000Y-9780798D01*
|
||||
X6835000Y-9780798D01*
|
||||
X6835000Y-2504951D01*
|
||||
D11*
|
||||
X7093277Y-10094782D02*
|
||||
X7093277Y-9894782D01*
|
||||
X7093277Y-9894782D02*
|
||||
X7140896Y-9894782D01*
|
||||
X7140896Y-9894782D02*
|
||||
X7169467Y-9904306D01*
|
||||
X7169467Y-9904306D02*
|
||||
X7188515Y-9923354D01*
|
||||
X7188515Y-9923354D02*
|
||||
X7198039Y-9942401D01*
|
||||
X7198039Y-9942401D02*
|
||||
X7207562Y-9980496D01*
|
||||
X7207562Y-9980496D02*
|
||||
X7207562Y-10009068D01*
|
||||
X7207562Y-10009068D02*
|
||||
X7198039Y-10047163D01*
|
||||
X7198039Y-10047163D02*
|
||||
X7188515Y-10066211D01*
|
||||
X7188515Y-10066211D02*
|
||||
X7169467Y-10085258D01*
|
||||
X7169467Y-10085258D02*
|
||||
X7140896Y-10094782D01*
|
||||
X7140896Y-10094782D02*
|
||||
X7093277Y-10094782D01*
|
||||
X7293277Y-10094782D02*
|
||||
X7293277Y-9961449D01*
|
||||
X7293277Y-9999544D02*
|
||||
X7302800Y-9980496D01*
|
||||
X7302800Y-9980496D02*
|
||||
X7312324Y-9970973D01*
|
||||
X7312324Y-9970973D02*
|
||||
X7331372Y-9961449D01*
|
||||
X7331372Y-9961449D02*
|
||||
X7350420Y-9961449D01*
|
||||
X7417086Y-10094782D02*
|
||||
X7417086Y-9961449D01*
|
||||
X7417086Y-9894782D02*
|
||||
X7407562Y-9904306D01*
|
||||
X7407562Y-9904306D02*
|
||||
X7417086Y-9913830D01*
|
||||
X7417086Y-9913830D02*
|
||||
X7426610Y-9904306D01*
|
||||
X7426610Y-9904306D02*
|
||||
X7417086Y-9894782D01*
|
||||
X7417086Y-9894782D02*
|
||||
X7417086Y-9913830D01*
|
||||
X7540896Y-10094782D02*
|
||||
X7521848Y-10085258D01*
|
||||
X7521848Y-10085258D02*
|
||||
X7512324Y-10066211D01*
|
||||
X7512324Y-10066211D02*
|
||||
X7512324Y-9894782D01*
|
||||
X7645658Y-10094782D02*
|
||||
X7626610Y-10085258D01*
|
||||
X7626610Y-10085258D02*
|
||||
X7617086Y-10066211D01*
|
||||
X7617086Y-10066211D02*
|
||||
X7617086Y-9894782D01*
|
||||
X7874229Y-10094782D02*
|
||||
X7874229Y-9894782D01*
|
||||
X7874229Y-9894782D02*
|
||||
X7940896Y-10037639D01*
|
||||
X7940896Y-10037639D02*
|
||||
X8007562Y-9894782D01*
|
||||
X8007562Y-9894782D02*
|
||||
X8007562Y-10094782D01*
|
||||
X8188515Y-10094782D02*
|
||||
X8188515Y-9990020D01*
|
||||
X8188515Y-9990020D02*
|
||||
X8178991Y-9970973D01*
|
||||
X8178991Y-9970973D02*
|
||||
X8159943Y-9961449D01*
|
||||
X8159943Y-9961449D02*
|
||||
X8121848Y-9961449D01*
|
||||
X8121848Y-9961449D02*
|
||||
X8102800Y-9970973D01*
|
||||
X8188515Y-10085258D02*
|
||||
X8169467Y-10094782D01*
|
||||
X8169467Y-10094782D02*
|
||||
X8121848Y-10094782D01*
|
||||
X8121848Y-10094782D02*
|
||||
X8102800Y-10085258D01*
|
||||
X8102800Y-10085258D02*
|
||||
X8093277Y-10066211D01*
|
||||
X8093277Y-10066211D02*
|
||||
X8093277Y-10047163D01*
|
||||
X8093277Y-10047163D02*
|
||||
X8102800Y-10028115D01*
|
||||
X8102800Y-10028115D02*
|
||||
X8121848Y-10018592D01*
|
||||
X8121848Y-10018592D02*
|
||||
X8169467Y-10018592D01*
|
||||
X8169467Y-10018592D02*
|
||||
X8188515Y-10009068D01*
|
||||
X8283753Y-9961449D02*
|
||||
X8283753Y-10161449D01*
|
||||
X8283753Y-9970973D02*
|
||||
X8302800Y-9961449D01*
|
||||
X8302800Y-9961449D02*
|
||||
X8340896Y-9961449D01*
|
||||
X8340896Y-9961449D02*
|
||||
X8359943Y-9970973D01*
|
||||
X8359943Y-9970973D02*
|
||||
X8369467Y-9980496D01*
|
||||
X8369467Y-9980496D02*
|
||||
X8378991Y-9999544D01*
|
||||
X8378991Y-9999544D02*
|
||||
X8378991Y-10056687D01*
|
||||
X8378991Y-10056687D02*
|
||||
X8369467Y-10075734D01*
|
||||
X8369467Y-10075734D02*
|
||||
X8359943Y-10085258D01*
|
||||
X8359943Y-10085258D02*
|
||||
X8340896Y-10094782D01*
|
||||
X8340896Y-10094782D02*
|
||||
X8302800Y-10094782D01*
|
||||
X8302800Y-10094782D02*
|
||||
X8283753Y-10085258D01*
|
||||
X8464705Y-10075734D02*
|
||||
X8474229Y-10085258D01*
|
||||
X8474229Y-10085258D02*
|
||||
X8464705Y-10094782D01*
|
||||
X8464705Y-10094782D02*
|
||||
X8455182Y-10085258D01*
|
||||
X8455182Y-10085258D02*
|
||||
X8464705Y-10075734D01*
|
||||
X8464705Y-10075734D02*
|
||||
X8464705Y-10094782D01*
|
||||
X8464705Y-9970973D02*
|
||||
X8474229Y-9980496D01*
|
||||
X8474229Y-9980496D02*
|
||||
X8464705Y-9990020D01*
|
||||
X8464705Y-9990020D02*
|
||||
X8455182Y-9980496D01*
|
||||
X8455182Y-9980496D02*
|
||||
X8464705Y-9970973D01*
|
||||
X8464705Y-9970973D02*
|
||||
X8464705Y-9990020D01*
|
||||
M02*
|
12
PCB/Export/Taiko IoBoard-NPTH.drl
Normal file
@ -0,0 +1,12 @@
|
||||
M48
|
||||
; DRILL file {KiCad 8.0.1} date 2024-04-30T12:08:56+0200
|
||||
; FORMAT={-:-/ absolute / metric / decimal}
|
||||
; #@! TF.CreationDate,2024-04-30T12:08:56+02:00
|
||||
; #@! TF.GenerationSoftware,Kicad,Pcbnew,8.0.1
|
||||
; #@! TF.FileFunction,NonPlated,1,2,NPTH
|
||||
FMAT,2
|
||||
METRIC
|
||||
%
|
||||
G90
|
||||
G05
|
||||
M30
|
2603
PCB/Export/Taiko IoBoard-PTH-drl_map.gbr
Normal file
92
PCB/Export/Taiko IoBoard-PTH.drl
Normal file
@ -0,0 +1,92 @@
|
||||
M48
|
||||
; DRILL file {KiCad 8.0.1} date 2024-04-30T12:08:56+0200
|
||||
; FORMAT={-:-/ absolute / metric / decimal}
|
||||
; #@! TF.CreationDate,2024-04-30T12:08:56+02:00
|
||||
; #@! TF.GenerationSoftware,Kicad,Pcbnew,8.0.1
|
||||
; #@! TF.FileFunction,Plated,1,2,PTH
|
||||
FMAT,2
|
||||
METRIC
|
||||
; #@! TA.AperFunction,Plated,PTH,ViaDrill
|
||||
T1C0.300
|
||||
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
|
||||
T2C0.800
|
||||
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
|
||||
T3C2.200
|
||||
%
|
||||
G90
|
||||
G05
|
||||
T1
|
||||
X121.1Y-30.135
|
||||
X121.1Y-47.529
|
||||
X121.1Y-65.0
|
||||
X121.1Y-82.535
|
||||
T2
|
||||
X72.346Y-80.812
|
||||
X72.346Y-83.352
|
||||
X72.346Y-85.892
|
||||
X72.35Y-32.554
|
||||
X72.35Y-35.094
|
||||
X72.35Y-37.634
|
||||
X72.35Y-40.174
|
||||
X72.35Y-42.714
|
||||
X72.35Y-45.254
|
||||
X72.35Y-47.794
|
||||
X72.35Y-50.334
|
||||
X72.35Y-52.874
|
||||
X72.35Y-55.414
|
||||
X72.35Y-57.954
|
||||
X72.35Y-60.494
|
||||
X72.35Y-63.034
|
||||
X72.35Y-65.574
|
||||
X72.35Y-68.114
|
||||
X72.35Y-70.654
|
||||
X72.35Y-73.194
|
||||
X72.35Y-75.734
|
||||
X72.35Y-78.274
|
||||
X95.21Y-32.554
|
||||
X95.21Y-35.094
|
||||
X95.21Y-37.634
|
||||
X95.21Y-40.174
|
||||
X95.21Y-42.714
|
||||
X95.21Y-45.254
|
||||
X95.21Y-47.794
|
||||
X95.21Y-50.334
|
||||
X95.21Y-52.874
|
||||
X95.21Y-55.414
|
||||
X95.21Y-57.954
|
||||
X95.21Y-60.494
|
||||
X95.21Y-63.034
|
||||
X95.21Y-65.574
|
||||
X95.21Y-68.114
|
||||
X95.21Y-70.654
|
||||
X95.21Y-73.194
|
||||
X95.21Y-75.734
|
||||
X95.21Y-78.274
|
||||
X95.21Y-80.814
|
||||
X95.21Y-83.354
|
||||
X95.21Y-85.894
|
||||
X101.22Y-52.88
|
||||
X101.22Y-70.319
|
||||
X101.22Y-87.841
|
||||
X101.63Y-35.516
|
||||
X103.76Y-50.34
|
||||
X103.76Y-55.42
|
||||
X103.76Y-67.779
|
||||
X103.76Y-72.859
|
||||
X103.76Y-85.301
|
||||
X103.76Y-90.381
|
||||
X104.17Y-32.976
|
||||
X104.17Y-38.056
|
||||
X126.207Y-34.455
|
||||
X126.207Y-36.455
|
||||
X126.207Y-51.8
|
||||
X126.207Y-53.8
|
||||
X126.207Y-69.258
|
||||
X126.207Y-71.258
|
||||
X126.207Y-86.78
|
||||
X126.207Y-88.78
|
||||
T3
|
||||
X71.35Y-28.054
|
||||
X117.6Y-28.054
|
||||
X117.6Y-95.054
|
||||
M30
|
BIN
PCB/Images/Don.bmp
Normal file
After Width: | Height: | Size: 206 KiB |
BIN
PCB/Images/Fox.bmp
Normal file
After Width: | Height: | Size: 1.3 MiB |
133
PCB/Taiko IoBoard.kicad_dru
Normal file
@ -0,0 +1,133 @@
|
||||
(version 1)
|
||||
# Custom Design Rules (DRC) for KiCAD 7.0 (Stored in '<project>.kicad_dru' file).
|
||||
#
|
||||
# Matching JLCPCB capabilities: https://jlcpcb.com/capabilities/pcb-capabilities
|
||||
#
|
||||
# KiCad documentation: https://docs.kicad.org/master/id/pcbnew/pcbnew_advanced.html#custom_design_rules
|
||||
#
|
||||
# Inspiration
|
||||
# - https://gist.github.com/darkxst/f713268e5469645425eed40115fb8b49 (with comments)
|
||||
# - https://gist.github.com/denniskupec/e163d13b0a64c2044bd259f64659485e (with comments)
|
||||
|
||||
# TODO new rule: NPTH pads.
|
||||
# Inner diameter of pad should be 0.4-0.5 mm larger than NPTH drill diameter.
|
||||
# JLCPCB: "We make NPTH via dry sealing film process, if customer would like a NPTH but around with pad/copper, our engineer will dig out around pad/copper about 0.2mm-0.25mm, otherwise the metal potion will be flowed into the hole and it becomes a PTH. (there will be no copper dig out optimization for single board)."
|
||||
|
||||
# TODO: new rule for plated slots: min diameter/width 0.5mm
|
||||
# JLCPCB: "The minimum plated slot width is 0.5mm, which is drawn with a pad."
|
||||
|
||||
# TODO new rule: non-plated slots: min diameter/width 1.0mm
|
||||
# JLCPCB: "The minimum Non-Plated Slot Width is 1.0mm, please draw the slot outline in the mechanical layer(GML or GKO)""
|
||||
|
||||
(rule "Track width, outer layer (1oz copper)"
|
||||
(layer outer)
|
||||
(condition "A.Type == 'track'")
|
||||
(constraint track_width (min 0.127mm))
|
||||
)
|
||||
|
||||
(rule "Track spacing, outer layer (1oz copper)"
|
||||
(layer outer)
|
||||
(condition "A.Type == 'track' && B.Type == A.Type")
|
||||
(constraint clearance (min 0.127mm))
|
||||
)
|
||||
|
||||
(rule "Track width, inner layer"
|
||||
(layer inner)
|
||||
(condition "A.Type == 'track'")
|
||||
(constraint track_width (min 0.09mm))
|
||||
)
|
||||
|
||||
(rule "Track spacing, inner layer"
|
||||
(layer inner)
|
||||
(condition "A.Type == 'track' && B.Type == A.Type")
|
||||
(constraint clearance (min 0.09mm))
|
||||
)
|
||||
|
||||
(rule "Silkscreen text"
|
||||
(layer "?.Silkscreen")
|
||||
(condition "A.Type == 'Text' || A.Type == 'Text Box'")
|
||||
(constraint text_thickness (min 0.15mm))
|
||||
(constraint text_height (min 1mm))
|
||||
)
|
||||
|
||||
(rule "Pad to Silkscreen"
|
||||
(layer outer)
|
||||
(condition "A.Type == 'pad' && B.Layer == '?.Silkscreen'")
|
||||
(constraint silk_clearance (min 0.15mm))
|
||||
)
|
||||
|
||||
(rule "Edge (routed) to track clearance"
|
||||
(condition "A.Type == 'track'")
|
||||
(constraint edge_clearance (min 0.3mm))
|
||||
)
|
||||
|
||||
#(rule "Edge (v-cut) to track clearance"
|
||||
# (condition "A.Type == 'track'")
|
||||
# (constraint edge_clearance (min 0.4mm))
|
||||
#)
|
||||
|
||||
# JLCPCB restrictions ambiguous:
|
||||
# Illustration: 0.2 mm, 1&2 layer: 0.3 mm, multilayer: "(0.15mm more costly)"
|
||||
# This rule handles diameter minimum and maximum for ALL holes.
|
||||
# Other specialized rules handle restrictions (e.g. Via, PTH, NPTH)
|
||||
(rule "Hole diameter"
|
||||
(constraint hole_size (min 0.2mm) (max 6.3mm))
|
||||
)
|
||||
|
||||
(rule "Hole (NPTH) diameter"
|
||||
(layer outer)
|
||||
(condition "!A.isPlated()")
|
||||
(constraint hole_size (min 0.5mm))
|
||||
)
|
||||
|
||||
# TODO: Hole to board edge ≥ 1 mm. Min. board size 10 × 10 mm
|
||||
(rule "Hole (castellated) diameter"
|
||||
(layer outer)
|
||||
(condition "A.Type == 'pad' && A.Fabrication_Property == 'Castellated pad'")
|
||||
(constraint hole_size (min 0.6mm))
|
||||
)
|
||||
|
||||
# JLCPCB: "Via diameter should be 0.1mm(0.15mm preferred) larger than Via hole size" (illustration shows diameters for both dimensions)
|
||||
# JLCPCB: PTH: "The annular ring size will be enlarged to 0.15mm in production."
|
||||
(rule "Annular ring width (via and PTH)"
|
||||
(layer outer)
|
||||
(condition "A.isPlated()")
|
||||
(constraint annular_width (min 0.075mm))
|
||||
)
|
||||
|
||||
(rule "Clearance: hole to hole (perimeter), different nets"
|
||||
(layer outer)
|
||||
(condition "A.Net != B.Net")
|
||||
(constraint hole_to_hole (min 0.5mm))
|
||||
)
|
||||
|
||||
(rule "Clearance: hole to hole (perimeter), same net"
|
||||
(layer outer)
|
||||
(condition "A.Net == B.Net")
|
||||
(constraint hole_to_hole (min 0.254mm))
|
||||
)
|
||||
|
||||
(rule "Clearance: track to NPTH hole (perimeter)"
|
||||
# (condition "A.Pad_Type == 'NPTH, mechanical' && B.Type == 'track' && A.Net != B.Net")
|
||||
(condition "!A.isPlated() && B.Type == 'track' && A.Net != B.Net")
|
||||
(constraint hole_clearance (min 0.254mm))
|
||||
)
|
||||
|
||||
(rule "Clearance: track to PTH hole perimeter"
|
||||
(condition "A.isPlated() && B.Type == 'track' && A.Net != B.Net")
|
||||
(constraint hole_clearance (min 0.33mm))
|
||||
)
|
||||
|
||||
# TODO: try combining with rule "Clearance: PTH to track, different nets"
|
||||
(rule "Clearance: track to pad"
|
||||
(condition "A.Type == 'pad' && B.Type == 'track' && A.Net != B.Net")
|
||||
(constraint clearance (min 0.2mm))
|
||||
)
|
||||
|
||||
(rule "Clearance: pad/via to pad/via"
|
||||
(layer outer)
|
||||
# (condition "(A.Type == 'Pad' || A.Type == 'Via') && (B.Type == 'Pad' || B.Type == 'Via') && A.Net != B.Net")
|
||||
(condition "A.isPlated() && B.isPlated() && A.Net != B.Net")
|
||||
(constraint clearance (min 0.127mm))
|
||||
)
|
||||
|
15360
PCB/Taiko IoBoard.kicad_pcb
Normal file
645
PCB/Taiko IoBoard.kicad_pro
Normal file
@ -0,0 +1,645 @@
|
||||
{
|
||||
"board": {
|
||||
"3dviewports": [],
|
||||
"design_settings": {
|
||||
"defaults": {
|
||||
"apply_defaults_to_fp_fields": false,
|
||||
"apply_defaults_to_fp_shapes": false,
|
||||
"apply_defaults_to_fp_text": false,
|
||||
"board_outline_line_width": 0.05,
|
||||
"copper_line_width": 0.2,
|
||||
"copper_text_italic": false,
|
||||
"copper_text_size_h": 1.5,
|
||||
"copper_text_size_v": 1.5,
|
||||
"copper_text_thickness": 0.3,
|
||||
"copper_text_upright": false,
|
||||
"courtyard_line_width": 0.05,
|
||||
"dimension_precision": 4,
|
||||
"dimension_units": 3,
|
||||
"dimensions": {
|
||||
"arrow_length": 1270000,
|
||||
"extension_offset": 500000,
|
||||
"keep_text_aligned": true,
|
||||
"suppress_zeroes": false,
|
||||
"text_position": 0,
|
||||
"units_format": 1
|
||||
},
|
||||
"fab_line_width": 0.1,
|
||||
"fab_text_italic": false,
|
||||
"fab_text_size_h": 1.0,
|
||||
"fab_text_size_v": 1.0,
|
||||
"fab_text_thickness": 0.15,
|
||||
"fab_text_upright": false,
|
||||
"other_line_width": 0.1,
|
||||
"other_text_italic": false,
|
||||
"other_text_size_h": 1.0,
|
||||
"other_text_size_v": 1.0,
|
||||
"other_text_thickness": 0.15,
|
||||
"other_text_upright": false,
|
||||
"pads": {
|
||||
"drill": 2.2,
|
||||
"height": 3.8,
|
||||
"width": 3.8
|
||||
},
|
||||
"silk_line_width": 0.1,
|
||||
"silk_text_italic": false,
|
||||
"silk_text_size_h": 1.0,
|
||||
"silk_text_size_v": 1.0,
|
||||
"silk_text_thickness": 0.1,
|
||||
"silk_text_upright": false,
|
||||
"zones": {
|
||||
"min_clearance": 0.5
|
||||
}
|
||||
},
|
||||
"diff_pair_dimensions": [],
|
||||
"drc_exclusions": [
|
||||
"lib_footprint_issues|83615822|84313356|3184cf6f-cd6a-43b8-b31d-20707554a607|00000000-0000-0000-0000-000000000000",
|
||||
"lib_footprint_issues|83730666|90778872|2d58ae78-a2a2-4350-a7a7-fca4dc71234d|00000000-0000-0000-0000-000000000000",
|
||||
"silk_overlap|100300000|52279726|3d0b53af-89a3-4692-9176-9d80a8dd8df0|af4cd8b5-ef37-4e8a-85f9-9b99ca0d5098",
|
||||
"silk_overlap|100300000|53479726|eb74409d-0aa1-42b9-9310-e513fc397358|af4cd8b5-ef37-4e8a-85f9-9b99ca0d5098",
|
||||
"silk_overlap|100300000|69719125|aa3a19e8-cabd-46a2-aea1-704fa9b033f8|0a5b53c5-6ab2-4446-8a8d-56be5616a8c8",
|
||||
"silk_overlap|100300000|70919125|4a0ecbc0-c280-4396-8d34-82e9b577a220|0a5b53c5-6ab2-4446-8a8d-56be5616a8c8",
|
||||
"silk_overlap|100300000|87241262|6cff2727-0adc-4ef5-a59d-e37fcbdbb845|5a22e76f-d33e-46ff-8422-76172909934b",
|
||||
"silk_overlap|100300000|88441262|ba60af80-a9b8-4d14-ab59-ee4fb7b3977e|5a22e76f-d33e-46ff-8422-76172909934b",
|
||||
"silk_overlap|100710000|34916262|27d0e007-4066-4042-9504-b0783e553980|6764ea03-b931-45cc-9999-3f821450a6f6",
|
||||
"silk_overlap|100710000|36116262|5baae625-45d0-4f20-b9f5-a57fbac28c3f|6764ea03-b931-45cc-9999-3f821450a6f6",
|
||||
"silk_overlap|104600000|49579726|43417ce2-d7db-4522-a9fb-b5db0e4376d6|b4b1fd62-47ef-47be-996c-9ac6fc3467ff",
|
||||
"silk_overlap|104600000|56179726|8667d25c-bf73-4db6-b4c7-c2f0d3cbce02|392f30c6-a3d6-43c8-a987-2542ccdeaa4f",
|
||||
"silk_overlap|104600000|67019125|f9c7c2a3-cf27-4437-9904-9b246bf143df|b98a80f7-2cb7-4520-a859-47a164eeff8a",
|
||||
"silk_overlap|104600000|73619125|df50e9e9-9a70-4997-ac1d-e0589d686a71|55c24e24-6fd6-4155-bd18-a2930904e93d",
|
||||
"silk_overlap|104600000|84541262|e8ecbc7d-d5bb-463f-94d1-14eea84bc50c|bb978151-c231-475b-bf27-e742189c64ee",
|
||||
"silk_overlap|104600000|91141262|f45cbf74-ff40-4c2c-a67a-a0236c9144c1|c2ec3eff-2444-4555-b29a-c12e06679978",
|
||||
"silk_overlap|105010000|32216262|76d7da63-f0e3-444e-a2c4-00661998cad8|93a59ae9-f38c-4a65-93c4-59ca9d45b847",
|
||||
"silk_overlap|105010000|38816262|eba9d2e1-04f7-4de8-b057-d98949aa1a92|47f27375-ffd6-4160-8bcc-099ffc51c2ab",
|
||||
"silk_overlap|114433368|32122637|f87842bc-8cd5-48c7-a4c2-6575ea54ead1|0a1ba907-dfb3-4ad3-af4e-400021989a48",
|
||||
"silk_overlap|114433368|37272637|f87842bc-8cd5-48c7-a4c2-6575ea54ead1|8fe88d2b-85fd-461b-8ad7-8f1cc6a45efc",
|
||||
"silk_overlap|114433368|49467351|62e4b0fe-3d60-4355-917a-b073d4a48185|8201dd67-28bd-435a-b8c7-efcb141b083e",
|
||||
"silk_overlap|114433368|54617351|62e4b0fe-3d60-4355-917a-b073d4a48185|5eca6cea-61f1-4a99-814a-8072673e99fb",
|
||||
"silk_overlap|114433368|66925500|34ef2b16-fa78-493b-87f2-1c9e95ae8f9b|886b9f17-38e8-46a5-acd3-337eea87fc0f",
|
||||
"silk_overlap|114433368|72075500|34ef2b16-fa78-493b-87f2-1c9e95ae8f9b|04fe42f2-b021-4e00-a3c9-9279c4a0aed2",
|
||||
"silk_overlap|114433368|84447637|d67af12c-31f9-4ee9-b97a-677900e04160|89ae2855-f182-4fd5-83b2-698e2c97defd",
|
||||
"silk_overlap|114433368|89597637|d67af12c-31f9-4ee9-b97a-677900e04160|4d8e9983-977c-45c5-94dc-61a1461b445f",
|
||||
"silk_overlap|120733368|33646637|f87842bc-8cd5-48c7-a4c2-6575ea54ead1|1f310ec7-f310-4636-a85e-eef2efea7ef3",
|
||||
"silk_overlap|120733368|38796637|f87842bc-8cd5-48c7-a4c2-6575ea54ead1|3daa1bce-4144-46bd-9f90-eb07de674007",
|
||||
"silk_overlap|120733368|50991351|62e4b0fe-3d60-4355-917a-b073d4a48185|c3c7dbde-73d2-4aa2-9554-4fda1635daca",
|
||||
"silk_overlap|120733368|56141351|62e4b0fe-3d60-4355-917a-b073d4a48185|156f8cdf-6bb8-41e0-949a-eb3eff9ff653",
|
||||
"silk_overlap|120733368|68449500|34ef2b16-fa78-493b-87f2-1c9e95ae8f9b|07127cac-27bf-408c-a401-5584b02d3ebc",
|
||||
"silk_overlap|120733368|73599500|34ef2b16-fa78-493b-87f2-1c9e95ae8f9b|6564ef5e-8d6e-4c38-8f7c-c60c5d20bc03",
|
||||
"silk_overlap|120733368|85971637|d67af12c-31f9-4ee9-b97a-677900e04160|561a3a39-ac8f-4760-bd34-d1d3bce8a0f6",
|
||||
"silk_overlap|120733368|91121637|d67af12c-31f9-4ee9-b97a-677900e04160|4a4cc234-f58b-4a74-91a9-a34e6ecaa12b",
|
||||
"silk_overlap|126307290|33654803|3eaaa621-88d6-4032-8486-889f986db4bc|38855887-088c-474e-85be-79b315e4276e",
|
||||
"silk_overlap|126307290|37254803|71766b01-d7cf-4d9d-bf62-c792d20c795e|fec84bcc-4ce8-4d59-88f6-5c09ddf37ff9",
|
||||
"silk_overlap|126307290|50999517|e96ef8db-37a1-4af7-8eb6-1907719e9e38|acf824fd-130c-4f96-b19f-745ce2846edb",
|
||||
"silk_overlap|126307290|54599517|0ad1a526-6648-417e-b113-0e49e200e05c|568c694f-2f54-43fe-817f-bef1053f715c",
|
||||
"silk_overlap|126307290|68457666|332b7fb0-f4fb-4b49-ba3d-a77365baa81f|5f87d550-656d-4ba7-b017-93b81dcd5ec3",
|
||||
"silk_overlap|126307290|72057666|be07a185-9681-42f6-b9b4-c097fd8b4a51|4accc8f7-b8c6-4a38-ab19-f3149221526f",
|
||||
"silk_overlap|126307290|85979803|2c24d03c-436d-4ef8-b088-874e71cb8623|c7dc2ccf-f793-440b-8520-f0f13061abbf",
|
||||
"silk_overlap|126307290|89579803|7f400e85-9047-44a3-b8d2-876b994e2756|44ec84f2-7107-4162-8521-4f70c72eee4e"
|
||||
],
|
||||
"meta": {
|
||||
"version": 2
|
||||
},
|
||||
"rule_severities": {
|
||||
"annular_width": "error",
|
||||
"clearance": "error",
|
||||
"connection_width": "warning",
|
||||
"copper_edge_clearance": "error",
|
||||
"copper_sliver": "warning",
|
||||
"courtyards_overlap": "error",
|
||||
"diff_pair_gap_out_of_range": "error",
|
||||
"diff_pair_uncoupled_length_too_long": "error",
|
||||
"drill_out_of_range": "error",
|
||||
"duplicate_footprints": "warning",
|
||||
"extra_footprint": "warning",
|
||||
"footprint": "error",
|
||||
"footprint_symbol_mismatch": "warning",
|
||||
"footprint_type_mismatch": "ignore",
|
||||
"hole_clearance": "error",
|
||||
"hole_near_hole": "error",
|
||||
"invalid_outline": "error",
|
||||
"isolated_copper": "ignore",
|
||||
"item_on_disabled_layer": "error",
|
||||
"items_not_allowed": "error",
|
||||
"length_out_of_range": "error",
|
||||
"lib_footprint_issues": "warning",
|
||||
"lib_footprint_mismatch": "ignore",
|
||||
"malformed_courtyard": "error",
|
||||
"microvia_drill_out_of_range": "error",
|
||||
"missing_courtyard": "ignore",
|
||||
"missing_footprint": "warning",
|
||||
"net_conflict": "warning",
|
||||
"npth_inside_courtyard": "ignore",
|
||||
"padstack": "warning",
|
||||
"pth_inside_courtyard": "ignore",
|
||||
"shorting_items": "error",
|
||||
"silk_edge_clearance": "warning",
|
||||
"silk_over_copper": "ignore",
|
||||
"silk_overlap": "warning",
|
||||
"skew_out_of_range": "error",
|
||||
"solder_mask_bridge": "error",
|
||||
"starved_thermal": "error",
|
||||
"text_height": "warning",
|
||||
"text_thickness": "warning",
|
||||
"through_hole_pad_without_hole": "error",
|
||||
"too_many_vias": "error",
|
||||
"track_dangling": "warning",
|
||||
"track_width": "error",
|
||||
"tracks_crossing": "error",
|
||||
"unconnected_items": "error",
|
||||
"unresolved_variable": "error",
|
||||
"via_dangling": "warning",
|
||||
"zones_intersect": "error"
|
||||
},
|
||||
"rules": {
|
||||
"max_error": 0.005,
|
||||
"min_clearance": 0.0,
|
||||
"min_connection": 0.0,
|
||||
"min_copper_edge_clearance": 0.5,
|
||||
"min_hole_clearance": 0.25,
|
||||
"min_hole_to_hole": 0.25,
|
||||
"min_microvia_diameter": 0.2,
|
||||
"min_microvia_drill": 0.1,
|
||||
"min_resolved_spokes": 2,
|
||||
"min_silk_clearance": 0.0,
|
||||
"min_text_height": 0.8,
|
||||
"min_text_thickness": 0.08,
|
||||
"min_through_hole_diameter": 0.3,
|
||||
"min_track_width": 0.0,
|
||||
"min_via_annular_width": 0.1,
|
||||
"min_via_diameter": 0.5,
|
||||
"solder_mask_to_copper_clearance": 0.0,
|
||||
"use_height_for_length_calcs": true
|
||||
},
|
||||
"teardrop_options": [
|
||||
{
|
||||
"td_onpadsmd": true,
|
||||
"td_onroundshapesonly": false,
|
||||
"td_ontrackend": false,
|
||||
"td_onviapad": true
|
||||
}
|
||||
],
|
||||
"teardrop_parameters": [
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_round_shape",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
},
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_rect_shape",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
},
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_track_end",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
}
|
||||
],
|
||||
"track_widths": [],
|
||||
"tuning_pattern_settings": {
|
||||
"diff_pair_defaults": {
|
||||
"corner_radius_percentage": 80,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.2,
|
||||
"single_sided": false,
|
||||
"spacing": 1.0
|
||||
},
|
||||
"diff_pair_skew_defaults": {
|
||||
"corner_radius_percentage": 80,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.2,
|
||||
"single_sided": false,
|
||||
"spacing": 0.6
|
||||
},
|
||||
"single_track_defaults": {
|
||||
"corner_radius_percentage": 80,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.2,
|
||||
"single_sided": false,
|
||||
"spacing": 0.6
|
||||
}
|
||||
},
|
||||
"via_dimensions": [],
|
||||
"zones_allow_external_fillets": false
|
||||
},
|
||||
"ipc2581": {
|
||||
"dist": "",
|
||||
"distpn": "",
|
||||
"internal_id": "",
|
||||
"mfg": "",
|
||||
"mpn": ""
|
||||
},
|
||||
"layer_presets": [],
|
||||
"viewports": []
|
||||
},
|
||||
"boards": [],
|
||||
"cvpcb": {
|
||||
"equivalence_files": []
|
||||
},
|
||||
"erc": {
|
||||
"erc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"pin_map": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
],
|
||||
"rule_severities": {
|
||||
"bus_definition_conflict": "error",
|
||||
"bus_entry_needed": "error",
|
||||
"bus_to_bus_conflict": "error",
|
||||
"bus_to_net_conflict": "error",
|
||||
"conflicting_netclasses": "error",
|
||||
"different_unit_footprint": "error",
|
||||
"different_unit_net": "error",
|
||||
"duplicate_reference": "error",
|
||||
"duplicate_sheet_names": "error",
|
||||
"endpoint_off_grid": "warning",
|
||||
"extra_units": "error",
|
||||
"global_label_dangling": "warning",
|
||||
"hier_label_mismatch": "error",
|
||||
"label_dangling": "error",
|
||||
"lib_symbol_issues": "warning",
|
||||
"missing_bidi_pin": "warning",
|
||||
"missing_input_pin": "warning",
|
||||
"missing_power_pin": "error",
|
||||
"missing_unit": "warning",
|
||||
"multiple_net_names": "warning",
|
||||
"net_not_bus_member": "warning",
|
||||
"no_connect_connected": "warning",
|
||||
"no_connect_dangling": "warning",
|
||||
"pin_not_connected": "error",
|
||||
"pin_not_driven": "error",
|
||||
"pin_to_pin": "warning",
|
||||
"power_pin_not_driven": "error",
|
||||
"similar_labels": "warning",
|
||||
"simulation_model_issue": "ignore",
|
||||
"unannotated": "error",
|
||||
"unit_value_mismatch": "error",
|
||||
"unresolved_variable": "error",
|
||||
"wire_dangling": "error"
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"pinned_footprint_libs": [],
|
||||
"pinned_symbol_libs": []
|
||||
},
|
||||
"meta": {
|
||||
"filename": "Taiko IoBoard.kicad_pro",
|
||||
"version": 1
|
||||
},
|
||||
"net_settings": {
|
||||
"classes": [
|
||||
{
|
||||
"bus_width": 12,
|
||||
"clearance": 0.2,
|
||||
"diff_pair_gap": 0.25,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.2,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.3,
|
||||
"microvia_drill": 0.1,
|
||||
"name": "Default",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.2,
|
||||
"via_diameter": 0.6,
|
||||
"via_drill": 0.3,
|
||||
"wire_width": 6
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 3
|
||||
},
|
||||
"net_colors": null,
|
||||
"netclass_assignments": null,
|
||||
"netclass_patterns": []
|
||||
},
|
||||
"pcbnew": {
|
||||
"last_paths": {
|
||||
"gencad": "",
|
||||
"idf": "",
|
||||
"netlist": "",
|
||||
"plot": "Export/",
|
||||
"pos_files": "",
|
||||
"specctra_dsn": "",
|
||||
"step": "",
|
||||
"svg": "",
|
||||
"vrml": ""
|
||||
},
|
||||
"page_layout_descr_file": ""
|
||||
},
|
||||
"schematic": {
|
||||
"annotate_start_num": 0,
|
||||
"bom_fmt_presets": [],
|
||||
"bom_fmt_settings": {
|
||||
"field_delimiter": ",",
|
||||
"keep_line_breaks": false,
|
||||
"keep_tabs": false,
|
||||
"name": "CSV",
|
||||
"ref_delimiter": ",",
|
||||
"ref_range_delimiter": "",
|
||||
"string_delimiter": "\""
|
||||
},
|
||||
"bom_presets": [],
|
||||
"bom_settings": {
|
||||
"exclude_dnp": false,
|
||||
"fields_ordered": [
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Reference",
|
||||
"name": "Reference",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "Value",
|
||||
"name": "Value",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Datasheet",
|
||||
"name": "Datasheet",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Footprint",
|
||||
"name": "Footprint",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Qty",
|
||||
"name": "${QUANTITY}",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "DNP",
|
||||
"name": "${DNP}",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "#",
|
||||
"name": "${ITEM_NUMBER}",
|
||||
"show": false
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Description",
|
||||
"name": "Description",
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"filter_string": "",
|
||||
"group_symbols": true,
|
||||
"name": "",
|
||||
"sort_asc": true,
|
||||
"sort_field": "Reference"
|
||||
},
|
||||
"connection_grid_size": 50.0,
|
||||
"drawing": {
|
||||
"dashed_lines_dash_length_ratio": 12.0,
|
||||
"dashed_lines_gap_length_ratio": 3.0,
|
||||
"default_line_thickness": 6.0,
|
||||
"default_text_size": 50.0,
|
||||
"field_names": [],
|
||||
"intersheets_ref_own_page": false,
|
||||
"intersheets_ref_prefix": "",
|
||||
"intersheets_ref_short": false,
|
||||
"intersheets_ref_show": false,
|
||||
"intersheets_ref_suffix": "",
|
||||
"junction_size_choice": 3,
|
||||
"label_size_ratio": 0.375,
|
||||
"operating_point_overlay_i_precision": 3,
|
||||
"operating_point_overlay_i_range": "~A",
|
||||
"operating_point_overlay_v_precision": 3,
|
||||
"operating_point_overlay_v_range": "~V",
|
||||
"overbar_offset_ratio": 1.23,
|
||||
"pin_symbol_size": 25.0,
|
||||
"text_offset_ratio": 0.15
|
||||
},
|
||||
"legacy_lib_dir": "",
|
||||
"legacy_lib_list": [],
|
||||
"meta": {
|
||||
"version": 1
|
||||
},
|
||||
"net_format_name": "",
|
||||
"ngspice": {
|
||||
"fix_include_paths": true,
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"model_mode": 4,
|
||||
"workbook_filename": ""
|
||||
},
|
||||
"page_layout_descr_file": "",
|
||||
"plot_directory": "",
|
||||
"spice_current_sheet_as_root": false,
|
||||
"spice_external_command": "spice \"%I\"",
|
||||
"spice_model_current_sheet_as_root": true,
|
||||
"spice_save_all_currents": false,
|
||||
"spice_save_all_dissipations": false,
|
||||
"spice_save_all_voltages": false,
|
||||
"subpart_first_id": 65,
|
||||
"subpart_id_separator": 0
|
||||
},
|
||||
"sheets": [
|
||||
[
|
||||
"dc950acd-196c-43f3-b94e-dc134983eda5",
|
||||
"Racine"
|
||||
]
|
||||
],
|
||||
"text_variables": {}
|
||||
}
|
6981
PCB/Taiko IoBoard.kicad_sch
Normal file
2
PCB/Taiko IoBoard.round-tracks-config
Normal file
@ -0,0 +1,2 @@
|
||||
Default True 2.0 3
|
||||
False True False
|
128
README.md
@ -1,130 +1,78 @@
|
||||
[日本語のドキュメントはこちら](README_ja-JP.md)
|
||||
# Analog Taiko IO Board - ESP32 S3 DevkitC1
|
||||
|
||||
[中文文档在这里](README_zh-CN.md)
|
||||
Open-source project to make your own Taiko no Tatsujin IO Board for PC use or SD cabs converted to Nijiiro.
|
||||
It emulates an analog joystick to enable force sensing, just like how you would play on an official arcade machine.
|
||||
|
||||
![Taiko Drum Controller](./images/banner-taiko.png)
|
||||
|
||||
# Taiko Drum Controller - Arduino (ATmega32U4/ESP32)
|
||||
|
||||
Open-source hardware program to make your own Taiko no Tatsujin PC controller. It can emulate as a keyboard, or as an analog joystick to enable hitting force sensing - just like how you play on the arcade machine. Now also support 2 drums so you can enjoy the game together with your friends at home!
|
||||
![Taiko Drum Controller](./Images/banner-taiko.png)
|
||||
|
||||
## About this Project
|
||||
|
||||
This project aims to help you develop your own hardware taiko at home.
|
||||
|
||||
This is a hard fork of [ShikyC's](https://github.com/ShikyC/Taiko-Drum-Controller-Arduino) taiko controller project with some QOL improvements.
|
||||
It's aim is to provide accurate-enough arcade drum support for converted SD cabs or bootlegs running Taiko Nijiiro.
|
||||
![Converted bootleg cab](./Images/bootleg_cab.png)
|
||||
**This program is for personal and non-commercial use only.**
|
||||
|
||||
## What You Need
|
||||
|
||||
1. An Arduino Micro/Leonardo (ATmega32U4) board or an Arduino Nano ESP (ESP32) board.
|
||||
* An [ESP32 S3 DevKitC-1](https://docs.espressif.com/projects/esp-idf/en/stable/esp32s3/hw-reference/esp32s3/user-guide-devkitc-1.html) board.
|
||||
* 4 [JST PH 2.0](https://fr.aliexpress.com/item/1005004067623293.html) connectors (i'm using 90° ones but straight ones work too).
|
||||
* 4 [1206 LEDs](https://fr.aliexpress.com/item/1005005975741298.html) (2 Blue and 2 Red).
|
||||
* 8 1206 100kΩ resistors.
|
||||
* 4 bridge rectifier chips. This project uses [DB107S](https://www.rectron.com/public/product_datasheets/db101s-db107s.pdf) (see the Additional Notes section for details).
|
||||
* 4 10k variable resistors. This project uses [3362P-1-103](https://www.mouser.fr/datasheet/2/54/3362-776956.pdf)
|
||||
|
||||
Most ATmega32U4 boards work, but you need to verify that they support keyboard emulation; ATmega328P boards like Arduino Uno don't work.
|
||||
All of those parts can be found for next to nothing on aliexpress.
|
||||
|
||||
ESP32 is strongly recommended because it's significantly more powerful than ATmega32U4. This project uses an ESP32-WROOM-32 board.
|
||||
|
||||
2. 4 piezoelectric sensors.
|
||||
|
||||
3. 8 100kΩ resistors.
|
||||
|
||||
4. (Optional) 4 bridge rectifier chips such as [DB107](https://www.diodes.com/assets/Datasheets/products_inactive_data/ds21211_R5.pdf) (see the Additional Notes section for details).
|
||||
|
||||
5. (Optional) Some red and blue LEDs.
|
||||
|
||||
6. Necessary electronic components (breadboards and jumper wires, etc.).
|
||||
|
||||
7. Wood planks and cutting tools (only if you need to make your physical taiko drum from scratch). If you have an aftermarket taiko or a Big Power Lv. 5 drum, you can use them directly.
|
||||
|
||||
## Steps to Make the Controller
|
||||
|
||||
1. Make the drum and firmly glue the 4 piezoelectric sensors to the drum. Refer to the image for preferred locations of the sensors.
|
||||
|
||||
![Sensor Setup](./images/piezo_locations.png)
|
||||
|
||||
2. Connect the piezoelectric sensors and other components to the controller as follows (the polarity of the piezoelectric sensors don't matter);
|
||||
|
||||
The following schemes are for Arduino Micro boards. If you use a different board, refer to its documentations for the connection.
|
||||
|
||||
![Controller scheme](./images/scheme.png)
|
||||
|
||||
If you choose to add the bridge rectifiers, use the following scheme:
|
||||
|
||||
![Controller scheme with bridge rectifiers](./images/scheme_bridge.png)
|
||||
|
||||
3. Flash the firmware to the board.
|
||||
|
||||
You may need to fine-tune some parameters like `SAMPLE_CACHE_LENGTH`, `HIT_THRES`, `RESET_THRES`, and `sensitivity`. See the following section for details.
|
||||
|
||||
4. Have fun!
|
||||
You'll also need an IO Board PCB (you can find the gerber files in [here](./PCB/Export/)).
|
||||
I've used [JLCPCB](https://jlcpcb.com/) to order mine.
|
||||
|
||||
## Tuning the Parameters
|
||||
|
||||
1. Hit and reset threshold
|
||||
All the parameters are located in [params.h](./Firmware/params.h).
|
||||
|
||||
Set `DEBUG 1` (this disables the keyboard output and sends signal values from the serial port), flash the firmware, roll on one of the 4 areas of the drum, and visualize the graph from the output of the serial monitor. The hit threshold should be lower than your heaviest hit on the drum, and the reset threshold should be greater than the trough between roll hits. The reset value should also be below the hit value.
|
||||
### Player Select
|
||||
|
||||
Repeat the process for the rest 3 areas and find the best one that fits all.
|
||||
By setting `#define PLAYER_SELECT` to either `1` or `2`, you can set what player the board will act as. If you're using two of these, make sure that they each are set to a different player to avoid issues.
|
||||
|
||||
![Setting hit and reset values](./images/tune_hit_reset.png)
|
||||
The buildin led of the ESP32 S3 DevKitC1 will be either red or blue depending on that value !
|
||||
|
||||
2. Sampling length
|
||||
### Sensitivities
|
||||
|
||||
For maximum runtime speed, the `cache.h` library has been optimized to work with `SAMPLE_CACHE_LENGTH` window sizes of powers of 2. That means 2, 8, 16, and 32, etc. Practically 16 is the best value for Arduino, but if you have a powerful microcontroller that samples the input at the speed of at least 4000Hz or more, you can change the value to 32 for a smoother (in other words, less noisy) curve.
|
||||
Not all piezoelectric sensors are the same, and thus the captured signals from the 4 sensors may vary significantly. The sensitivity adjust trims are used to normalize those differences.
|
||||
|
||||
3. Sensitivities
|
||||
To facilitate setting those trims up, set `DEBUG` to `1`, flash the firmware, roll on one of the 4 areas of the drum, and visualize the graph from the output of the Serial Plotter.
|
||||
|
||||
Not all piezoelectric sensors are the same, and due to installation errors, the captured signals from the 4 sensors may vary significantly. The sensitivity values are multipliers to normalize the differences. In the following example, the right-don area generates a much higher value than the rest 3, so you can adjust `sensitivity` to `{1.0, 1.0, 0.5, 1.0}` to eliminate the issue.
|
||||
In the following example, the right-don area generates a much higher value than other 3, so you can adjust the `sensitivity` by turning the R_DON potentiometer to eliminate the issue.
|
||||
|
||||
![Setting sensitivity values](./images/tune_sensitivities.png)
|
||||
![Setting sensitivity values](./Images/tune_sensitivities.png)
|
||||
|
||||
Note that the installation of the sensors is very critical. You should make sure that the sensors are firmly attached on the wood and located properly.
|
||||
Note that the installation of the sensors is critical. You should make sure that the sensors are firmly attached on the wood and located properly, as seen on the picture below.
|
||||
|
||||
![Piezo locations](./Images/piezo_locations.png)
|
||||
|
||||
## Additional Notes
|
||||
|
||||
1. Why using bridge rectifiers
|
||||
### Why using bridge rectifiers
|
||||
|
||||
Without biasing the voltage of the piezoelectric sensors, their output voltage range is about -5V to +5V. However, the ADCs of the analog inputs only accepts positive voltage values (0-3.3V for ESP32 and 0-5V for ATmega32U4). When they receive a negative voltage, it's simply truncated to 0.
|
||||
|
||||
It's usually okay for normal electronic drums because we're just losing half of the input energy and it doesn't influence how we calculate the hitting time. But it can cause problems for *taiko* drums, especially with slow processors like ATmega32U4.
|
||||
Without biasing the voltage of the piezoelectric sensors, their output voltage range is about -5V to +5V. However, the ESP32 ADCs only accept positive voltage values from 0 to 3.3V. When they receive a negative voltage, it's simply truncated to 0.
|
||||
|
||||
In a taiko drum, all the 4 vibrating pieces are connected together, meaning that if you hit left-don, the processor also receives signals from left-kat, right-don, and right-kat. If the left-don piezoelectric sensor generates a negative voltage at the beginning and is truncated by the ADC, it will cause a minor "delay" of about 3 to 4 milliseconds, and the processor could incorrectly treat this hit as a right-don, a left-kat, or even a right-kat, whichever sends a highest positive value.
|
||||
|
||||
Using a bridge rectifier, all negative values are converted to positive. In other words, it's like the `abs()` function, ensuring that we don't lose any negative voltages.
|
||||
Using a bridge rectifier, all negative values are converted to positive. In other words, it's acting like a mathematical `abs()` function, ensuring that we don't miss any negative voltages.
|
||||
|
||||
![Why using bridge rectifiers](./images/bridge_signal.png)
|
||||
![Why using bridge rectifiers](./Images/bridge_signal.png)
|
||||
|
||||
# Taiko Controller - Analog Input Mode (Beta)
|
||||
### TaikoArcadeLoader
|
||||
|
||||
With ESP32-S2 or ESP32-S3 controllers, instead of keyboard emulation, the drum controller can work as a gamepad and send its axes values to the game (which also must support analog input). In this way, the game can recognize different force levels of the hit.
|
||||
You'll need to use a recent version of esuo1198's fork of [TaikoArcadeLoader](https://github.com/esuo1198/TaikoArcadeLoader) (Commit [945e104](https://github.com/esuo1198/TaikoArcadeLoader/commit/945e104) and up).
|
||||
|
||||
If you prefer to use the Arduino Micro/Leonardo board, please refer to the [Arduino XInput Library](https://github.com/dmadison/ArduinoXInput) to implement the gamepad.
|
||||
Open `config.toml` and enable analog input like so :
|
||||
|
||||
## What You Need
|
||||
|
||||
1. Make your drum or use Taiko Force Lv.5.
|
||||
|
||||
2. Flash `ESP32-S3-Analog/ESP32-S3-Analog.ino` to your controller.
|
||||
|
||||
3. A working ***game***, with these modifications:
|
||||
|
||||
- Backup and replace the `bnusio.dll` file in the game folder with the one here in the `extra/` folder.
|
||||
|
||||
This file is compiled from [this fork](https://github.com/ShikyC/TaikoArcadeLoader/tree/Refactor) and you can compile it by yourself if you want.
|
||||
|
||||
*This modified library only works with a specific game version. If it breaks your game, please clone the original repository, make the corrensponding modifications, and compile it.*
|
||||
|
||||
- Open the `gamecontrollerdb.txt` file in the game folder and add one entry under `#Windows`:
|
||||
|
||||
`030052a8694800006948000000000000,Taiko Controller,-leftx:-a0,+leftx:+a0,-lefty:-a1,+lefty:+a1,-rightx:-a2,+rightx:+a2,-righty:-a3,+righty:+a3,platform:Windows,`
|
||||
|
||||
This will tell the game that our ESP32 controller is a gamepad called "Taiko Controller", and map the axis to the standard SDL2 library so that the game can recognize the analog inputs.
|
||||
|
||||
- Open the `config.toml` file and add the following lines at the end:
|
||||
|
||||
```
|
||||
```toml
|
||||
[controller]
|
||||
analog = true
|
||||
```
|
||||
|
||||
Note that with `analog = true`, all the keyboard drum inputs are disabled. Sorry for this but it need further refactoring to make them work together. If you want to switch back to keyboard inputs, set `analog = false`.
|
||||
If the IO Board is detected but your game doesn't register any inputs, check in `gamecontrollerdb.txt` that you have the following entry under `#Windows`:
|
||||
|
||||
4. Launch the game and enjoy!
|
||||
`030052a8694800006948000000000000,Nijiiro Analog IO Board,-leftx:-a0,+leftx:+a0,-lefty:-a1,+lefty:+a1,-rightx:-a2,+rightx:+a2,-righty:-a3,+righty:+a3,platform:Windows,`
|
||||
|
130
README_ja-JP.md
@ -1,130 +0,0 @@
|
||||
[Click here for English documentation](README.md)
|
||||
|
||||
[中文文档在这里](README_zh-CN.md)
|
||||
|
||||
![太鼓コントローラ](./images/banner-taiko.png)
|
||||
|
||||
# Taiko Drum Controller - Arduino (ATmega32U4/ESP32)
|
||||
|
||||
自分の太鼓の達人PCコントローラを作るためのオープンソースハードウェアプログラム。キーボードとして、またはアーケードマシンで遊ぶように打撃力感知を有効にするアナログジョイスティックとしてエミュレートできます。今では2つのドラムもサポートしているので、家で友達と一緒にゲームを楽しむことができます!
|
||||
|
||||
## このプロジェクトについて
|
||||
|
||||
このプロジェクトは、自宅で自分のハードウェア太鼓を開発するのを助けることを目指しています。
|
||||
|
||||
**このプログラムは個人的かつ非商用のみに限ります。**
|
||||
|
||||
## 必要なもの
|
||||
|
||||
1. Arduino Micro/Leonardo (ATmega32U4) ボードまたは Arduino Nano ESP (ESP32) ボード。
|
||||
|
||||
ほとんどのATmega32U4ボードは動作しますが、キーボードエミュレーションをサポートしているかを確認する必要があります。Arduino UnoのようなATmega328Pボードは動作しません。
|
||||
|
||||
ESP32はATmega32U4よりも格段にパワフルなため、強く推奨されます。このプロジェクトではESP32-WROOM-32ボードを使用しています。
|
||||
|
||||
2. 4つの圧電センサ。
|
||||
|
||||
3. 8つの100kΩ抵抗。
|
||||
|
||||
4. (任意) DB107などのブリッジ整流器チップ(詳細は追加ノートセクションを参照)。
|
||||
|
||||
5. (任意) 赤と青のLEDいくつか。
|
||||
|
||||
6. 必要な電子部品(ブレッドボード、ジャンパーワイヤーなど)。
|
||||
|
||||
7. 木板と切削工具(自分で物理的な太鼓を一から作る必要がある場合のみ)。アフターマーケットの太鼓やBig Power Lv.5ドラムを持っている場合は、それらを直接使用できます。
|
||||
|
||||
## コントローラを作る手順
|
||||
|
||||
1. 太鼓を作り、4つの圧電センサを太鼓にしっかりと接着します。センサの好ましい位置については画像を参照してください。
|
||||
|
||||
![センサ設定](./images/piezo_locations.png)
|
||||
|
||||
2. 圧電センサと他のコンポーネントを以下の通りコントローラに接続します(圧電センサの極性は問いません);
|
||||
|
||||
以下のスキームはArduino Microボード用です。異なるボードを使用する場合は、接続についてそのドキュメンテーションを参照してください。
|
||||
|
||||
![コントローラスキーム](./images/scheme.png)
|
||||
|
||||
ブリッジ整流器を追加することを選択した場合、以下のスキームを使用してください:
|
||||
|
||||
![ブリッジ整流器付きコントローラスキーム](./images/scheme_bridge.png)
|
||||
|
||||
3. ファームウェアをボードにフラッシュします。
|
||||
|
||||
`SAMPLE_CACHE_LENGTH`、`HIT_THRES`、`RESET_THRES`、`sensitivity`などのパラメータを微調整する必要があるかもしれません。詳細は以下のセクションを参照してください。
|
||||
|
||||
4. 楽しんでください!
|
||||
|
||||
## パラメータの調整
|
||||
|
||||
1. ヒットとリセットの閾値
|
||||
|
||||
`DEBUG 1`を設定し(これによりキーボード出力が無効になり、シリアルポートから信号値が送信されます)、ファームウェアをフラッシュし、太鼓の4つの領域のいずれかでロールして、シリアルモニターの出力からグラフを視覚化します。ヒット閾値は太鼓の最も重いヒットよりも低く、リセット閾値はロールヒットの間のトラフよりも大きくする必要があります。リセット値はまた、ヒット値よりも低くする必要があります。
|
||||
|
||||
残りの3つの領域についてもプロセスを繰り返し、すべてに適合する最適なものを見つけます。
|
||||
|
||||
![ヒットとリセット値の設定](./images/tune_hit_reset.png)
|
||||
|
||||
2. サンプリング長
|
||||
|
||||
最大の実行時間速度のために、`cache.h`ライブラリは2のべき乗の`SAMPLE_CACHE_LENGTH`ウィンドウサイズで動作するように最適化されています。つまり2、8、16、32などです。実用的には16がArduinoにとって最適な値ですが、少なくとも4000Hz以上の速度で入力をサンプリングするパワフルなマイクロコントローラを持っている場合は、よりスムーズな(つまり、ノイズが少ない)カーブのために値を32に変更することができます。
|
||||
|
||||
3. 感度
|
||||
|
||||
すべての圧電センサが同じではなく、取り付けエラーにより、4つのセンサからキャプチャされる信号は大きく異なることがあります。感度値は、差異を正規化するための乗数です。以下の例では、右のドンエリアが他の3つよりもはるかに高い値を生成しているため、`sensitivity`を`{1.0, 1.0, 0.5, 1.0}`に調整して問題を解決できます。
|
||||
|
||||
![感度値の設定](./images/tune_sensitivities.png)
|
||||
|
||||
センサの取り付けは非常に重要です。センサが木にしっかりと取り付けられ、適切な位置にあることを確認してください。
|
||||
|
||||
## 追加ノート
|
||||
|
||||
1. ブリッジ整流器の使用理由
|
||||
|
||||
圧電センサの電圧を偏らせない場合、その出力電圧範囲は約-5Vから+5Vです。しかし、アナログ入力のADCは正の電圧値(ESP32の場合は0-3.3V、ATmega32U4の場合は0-5V)のみを受け付けます。負の電圧を受け取ると、単に0に切り捨てられます。
|
||||
|
||||
通常の電子ドラムでは、入力エネルギーの半分を失っても、ヒットタイミングの計算には影響しませんので問題ありません。しかし、*太鼓*のドラムでは、特にATmega32U4のような遅いプロセッサを使用すると問題が発生することがあります。
|
||||
|
||||
太鼓のドラムでは、4つの振動する部分がすべて繋がっているため、左のドンを叩くと、プロセッサは左のカツ、右のドン、右のカツからも信号を受信します。左のドンの圧電センサが最初に負の電圧を生成し、ADCによって切り捨てられると、約3〜4ミリ秒のわずかな「遅延」が発生し、プロセッサはこのヒットを誤って右のドン、左のカツ、または右のカツとして処理する可能性があります。どちらかが最高の正の値を送信した場合です。
|
||||
|
||||
ブリッジ整流器を使用すると、すべての負の値が正の値に変換されます。言い換えれば、それは`abs()`関数のようなもので、負の電圧を失わないことを保証します。
|
||||
|
||||
![ブリッジ整流器の使用理由](./images/bridge_signal.png)
|
||||
|
||||
# Taiko Controller - アナログ入力モード(Beta)
|
||||
|
||||
ESP32-S2またはESP32-S3コントローラーを使用すると、キーボードエミュレーションの代わりに、ドラムコントローラーがゲームパッドとして機能し、その軸の値をゲームに送信できます(ゲームもアナログ入力をサポートしている必要があります)。この方法では、ゲームはヒットの異なる力のレベルを認識できます。
|
||||
|
||||
Arduino Micro/Leonardoボードを使用する場合は、[Arduino XInputライブラリ](https://github.com/dmadison/ArduinoXInput)を参照して、ゲームパッドを実装してください。
|
||||
|
||||
## 必要なもの
|
||||
|
||||
1. 自分のドラムを作るか、Taiko Force Lv.5を使用してください。詳細はメインブランチをチェックしてください。
|
||||
|
||||
2. `ESP32-S3-Analog/ESP32-S3-Analog.ino`をコントローラーにフラッシュします。
|
||||
|
||||
3. 以下の変更を加えたゲーム:
|
||||
|
||||
- ゲームフォルダ内の`bnusio.dll`ファイルをバックアップし、`extra/`フォルダーこちらのファイルで置き換えてください。
|
||||
|
||||
このファイルは[このフォーク](https://github.com/ShikyC/TaikoArcadeLoader/tree/Refactor)からコンパイルされており、必要に応じて自分でコンパイルすることができます。
|
||||
|
||||
*この変更されたライブラリは特定のゲームバージョンでのみ機能します。ゲームが壊れた場合は、元のリポジトリをクローンして、対応する変更を加え、コンパイルしてください。*
|
||||
|
||||
- ゲームフォルダ内の`gamecontrollerdb.txt`ファイルを開き、`#Windows`の下に次のエントリを追加します:
|
||||
|
||||
`030052a8694800006948000000000000,Taiko Controller,-leftx:-a0,+leftx:+a0,-lefty:-a1,+lefty:+a1,-rightx:-a2,+rightx:+a2,-righty:-a3,+righty:+a3,platform:Windows,`
|
||||
|
||||
これにより、ゲームはESP32コントローラーが「Taiko Controller」というゲームパッドであることを認識し、標準のSDL2ライブラリに軸をマップするため、ゲームがアナログ入力を認識できるようになります。
|
||||
|
||||
- `config.toml`ファイルを開き、最後に次の行を追加します:
|
||||
|
||||
```
|
||||
[controller]
|
||||
analog = true
|
||||
```
|
||||
|
||||
`analog = true`で、すべてのキーボードドラム入力が無効になります。これはさらなるリファクタリングが必要ですが、一緒に機能させるために申し訳ありません。キーボード入力に戻したい場合は、`analog = false`に設定してください。
|
||||
|
||||
4. ゲームを起動して楽しんでください!
|
130
README_zh-CN.md
@ -1,130 +0,0 @@
|
||||
[Click here for English documentation](README.md)
|
||||
|
||||
[日本語のドキュメントはこちら](README_ja-JP.md)
|
||||
|
||||
![Taiko Drum Controller](./images/banner-taiko.png)
|
||||
|
||||
# Taiko Drum Controller - Arduino (ATmega32U4/ESP32)
|
||||
|
||||
开源硬件程序,帮助你制作自己的太鼓达人PC控制器。它可以模拟作为键盘,或者作为模拟摇杆以启用击打力感应 - 就像您在街机上玩一样。现在还支持2个鼓,这样您就可以和朋友们一起在家享受游戏乐趣了!
|
||||
|
||||
## 关于本项目
|
||||
|
||||
本项目旨在帮助你在家制作自己的硬件太鼓。
|
||||
|
||||
**该程序仅供个人和非商业用途。**
|
||||
|
||||
## 你需要准备
|
||||
|
||||
1. 一个Arduino Micro/Leonardo (ATmega32U4) 板或一个Arduino Nano ESP (ESP32) 板。
|
||||
|
||||
大多数ATmega32U4板都可以工作,但你需要验证它们是否支持键盘模拟;像Arduino Uno这样的ATmega328P板则不行。
|
||||
|
||||
强烈推荐使用ESP32,因为它比ATmega32U4强大得多。该项目使用了ESP32-WROOM-32板。
|
||||
|
||||
2. 4个压电传感器。
|
||||
|
||||
3. 8个100kΩ电阻。
|
||||
|
||||
4. (可选)4个桥式整流器芯片,比如[DB107](https://www.diodes.com/assets/Datasheets/products_inactive_data/ds21211_R5.pdf)(详见附加说明部分)。
|
||||
|
||||
5. (可选)一些红色和蓝色的LED灯。
|
||||
|
||||
6. 必要的电子组件(面包板、LED灯、跳线等)。
|
||||
|
||||
7. 木板和切割工具(仅在你需要从头开始制作实体太鼓时使用)。如果你有市售太鼓或大力鼓Lv.5,可以直接使用。
|
||||
|
||||
## 制作控制器的步骤
|
||||
|
||||
1. 制作鼓,并将4个压电传感器牢固地粘贴在鼓上。参考图片以了解传感器的首选位置。
|
||||
|
||||
![传感器设置](./images/piezo_locations.png)
|
||||
|
||||
2. 按照以下方案将压电传感器和其他组件连接到控制器(压电传感器的极性无关紧要);
|
||||
|
||||
以下方案适用于Arduino Micro板。如果你使用不同的板,请参考其文档了解连接信息。
|
||||
|
||||
![控制器方案](./images/scheme.png)
|
||||
|
||||
如果你选择添加桥式整流器,请使用以下方案:
|
||||
|
||||
![带桥式整流器的控制器方案](./images/scheme_bridge.png)
|
||||
|
||||
3. 将固件刷写到板上。
|
||||
|
||||
你可能需要微调一些参数,如`SAMPLE_CACHE_LENGTH`、`HIT_THRES`、`RESET_THRES`和`sensitivity`。详见下一节。
|
||||
|
||||
4. 玩得开心!
|
||||
|
||||
## 调整参数
|
||||
|
||||
1. 击打和重置阈值
|
||||
|
||||
设置`DEBUG 1`(这会禁用键盘输出并从串行端口发送信号值),刷写固件,在鼓的4个区域之一上滚动,然后从串行监视器的输出中查看图表。击打阈值应低于你在鼓上的最重击打,重置阈值应高于连续击打之间的低谷。重置值也应低于击打值。
|
||||
|
||||
为剩下的3个区域重复此过程,并找到适合所有区域的最佳值。
|
||||
|
||||
![设置击打和重置值](./images/tune_hit_reset.png)
|
||||
|
||||
2. 采样长度
|
||||
|
||||
为了最大化运行速度,`cache.h`库已优化为支持2的幂次方窗口大小的`SAMPLE_CACHE_LENGTH`。这意味着2、8、16、32等。实际上,对于Arduino来说16是最佳值,但如果你有一个能以至少4000Hz或更高速度采样输入的强大微控制器,你可以将值改为32,以获得更平滑(换句话说,更少噪声)的曲线。
|
||||
|
||||
3. 灵敏度
|
||||
|
||||
并非所有压电传感器都是相同的,由于安装错误,4个传感器捕获的信号可能有显著差异。灵敏度值是用来规范这些差异的乘数。在以下示例中,右边的don区域产生的值比其余3个区域高得多,所以你可以调整`sensitivity`为`{1.0, 1.0, 0.5, 1.0}`来解决这个问题。
|
||||
|
||||
![设置灵敏度值](./images/tune_sensitivities.png)
|
||||
|
||||
请注意,传感器的安装非常关键。你应该确保传感器牢固地贴在木头上,并且位置适当。
|
||||
|
||||
## 附加说明
|
||||
|
||||
1. 为什么使用桥式整流器
|
||||
|
||||
如果不对压电传感器的电压进行偏置,它们的输出电压范围约为-5V到+5V。然而,模拟输入的ADC只接受正电压值(ESP32为0-3.3V,ATmega32U4为0-5V)。当它们接收到负电压时,通常会被简单地截断为0。
|
||||
|
||||
对于普通的电子鼓来说,这通常没问题,因为我们只是失去了一半的输入能量,而这并不影响我们计算击打时间的方式。但是对于*太鼓*鼓来说,特别是像ATmega32U4这样的慢处理器,可能会造成问题。
|
||||
|
||||
在太鼓鼓中,所有4个振动部件都连接在一起,这意味着如果你击打左边的don,处理器也会接收到左边的kat、右边的don和右边的kat的信号。如果左边的don压电传感器一开始就产生负电压,并被ADC截断,它将导致约3到4毫秒的轻微“延迟”,处理器可能会错误地将这次击打视为右边的don、左边的kat甚至右边的kat,取决于哪个发送了最高的正值。
|
||||
|
||||
使用桥式整流器,所有负值都转换为正值。换句话说,就像`abs()`函数,确保我们不会丢失任何负电压。
|
||||
|
||||
![为什么使用桥式整流器](./images/bridge_signal.png)
|
||||
|
||||
# Taiko Controller - 模拟输入模式
|
||||
|
||||
使用ESP32-S2或ESP32-S3控制器,代替键盘仿真,鼓控制器可以作为游戏手柄工作,并将其轴值发送给游戏(游戏也必须支持模拟输入)。这样,游戏可以识别击打的不同力度级别。
|
||||
|
||||
如果您更喜欢使用Arduino Micro/Leonardo板,请参考[Arduino XInput库](https://github.com/dmadison/ArduinoXInput)来实现游戏手柄。
|
||||
|
||||
## 你需要什么
|
||||
|
||||
1. 制作你的鼓或使用Taiko Force Lv.5。详情请查看主分支。
|
||||
|
||||
2. 将`ESP32-S3-Analog/ESP32-S3-Analog.ino`刷写到你的控制器。
|
||||
|
||||
3. 一个能正常运行的***游戏***,并进行以下修改:
|
||||
|
||||
- 备份并替换游戏文件夹中的`bnusio.dll`文件,使用这里`extra/`文件夹中的文件。
|
||||
|
||||
这个文件是从[这个仓库](https://github.com/ShikyC/TaikoArcadeLoader/tree/Refactor)编译的,如果你愿意,你也可以自己编译。
|
||||
|
||||
*这个修改过的库只适用于特定版本的游戏。如果它破坏了你的游戏,请克隆[原始仓库](https://github.com/BroGamer4256/TaikoArcadeLoader),进行相应的修改,并编译它。*
|
||||
|
||||
- 打开游戏文件夹中的`gamecontrollerdb.txt`文件,并在`#Windows`下添加一条条目:
|
||||
|
||||
`030052a8694800006948000000000000,Taiko Controller,-leftx:-a0,+leftx:+a0,-lefty:-a1,+lefty:+a1,-rightx:-a2,+rightx:+a2,-righty:-a3,+righty:+a3,platform:Windows,`
|
||||
|
||||
这将告诉游戏我们的ESP32控制器是一个名为“Taiko Controller”的游戏手柄,并将轴映射到标准SDL2库,以便游戏能够识别模拟输入。
|
||||
|
||||
- 打开`config.toml`文件,并在末尾添加以下行:
|
||||
|
||||
```
|
||||
[controller]
|
||||
analog = true
|
||||
```
|
||||
|
||||
请注意,使用`analog = true`时,所有键盘鼓输入都将被禁用。对此表示抱歉,但它需要进一步重构才能同时工作。如果你想切换回键盘输入,请设置`analog = false`。
|
||||
|
||||
4. 开始游玩咚!
|
Before Width: | Height: | Size: 422 KiB |
Before Width: | Height: | Size: 161 KiB |
Before Width: | Height: | Size: 140 KiB |
Before Width: | Height: | Size: 52 KiB |