[Keyboard] Add support for jj4x4 numpad/macropad by Kprepublic (#5016)
* added keyboard jj4x4, a shorter version of the jj40 * removed useless file * edited jj4x4 readme.md * optimized array size in jj4x4 config.h, removed reference to jj40 layouts from rules.mk * removed custom matrix for this ps2avrgb board, refactored column and row pinspull/3615/head^2
parent
d4e1e712f6
commit
7df9e584fa
@ -0,0 +1,71 @@
|
|||||||
|
# jj4x4
|
||||||
|
|
||||||
|
![jj4x4](https://cdn.shopify.com/s/files/1/2711/4238/products/JJ4x4case-1_1024x1024.jpg?v=1532325339)
|
||||||
|
|
||||||
|
A 4x4 keypad kit made and KPRepublic on AliExpress. This is a chopped off version of the jj40 with rearranged keys.
|
||||||
|
|
||||||
|
Keyboard Maintainer: [QMK Community](https://github.com/qmk)
|
||||||
|
Hardware Supported: Atmega32A
|
||||||
|
Hardware Availability: [AliExpress](https://www.aliexpress.com/item/jj4x4-jj4X4-16-keys-Custom-Mechanical-Keyboard-PCB-programmed-numpad-layouts-bface-firmware-with-rgb-bottom/32901955446.html?spm=2114.search0104.3.7.3ebf431ae1d9ic&ws_ab_test=searchweb0_0,searchweb201602_4_10065_10130_10068_10547_319_317_10548_10545_10696_453_10084_454_10083_433_10618_431_10307_537_536_10902_10059_10884_10887_321_322_10103,searchweb201603_6,ppcSwitch_0&algo_expid=9d1891dd-80af-4793-a889-5a62e1fdfdd8-1&algo_pvid=9d1891dd-80af-4793-a889-5a62e1fdfdd8&transAbTest=ae803_5)
|
||||||
|
|
||||||
|
Make example for this keyboard (after setting up your build environment):
|
||||||
|
|
||||||
|
make jj4x4:default:program
|
||||||
|
|
||||||
|
See [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) then the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information.
|
||||||
|
|
||||||
|
Note that this is a complete replacement for the firmware, so you won't be
|
||||||
|
using Bootmapper Client to change any keyboard settings, since not all the
|
||||||
|
USB report options are supported.
|
||||||
|
|
||||||
|
In addition you may need the AVR toolchain and `bootloadHID` ([GitHub repo](https://github.com/whiteneon/bootloadHID)) for flashing:
|
||||||
|
|
||||||
|
For macOS:
|
||||||
|
```
|
||||||
|
$ brew cask install crosspack-avr
|
||||||
|
$ brew install --HEAD https://raw.githubusercontent.com/robertgzr/homebrew-tap/master/bootloadhid.rb
|
||||||
|
```
|
||||||
|
|
||||||
|
For Linux:
|
||||||
|
```
|
||||||
|
$ sudo apt install libusb-dev
|
||||||
|
$ wget https://www.obdev.at/downloads/vusb/bootloadHID.2012-12-08.tar.gz
|
||||||
|
$ tar -xzf bootloadHID.2012-12-08.tar.gz
|
||||||
|
$ cd bootloadHID.2012-12-08/commandline
|
||||||
|
$ make
|
||||||
|
$ sudo cp bootloadHID /usr/bin
|
||||||
|
```
|
||||||
|
|
||||||
|
In order to use the `./program` script, which can reboot the board into
|
||||||
|
the bootloader, you'll need Python 2 with PyUSB installed:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ pip install pyusb
|
||||||
|
```
|
||||||
|
|
||||||
|
If you prefer (or are having issues with a `program` flash), you can just build it (`make jj40:<keymap-name>` and flash the firmware (`.hex` file) directly with
|
||||||
|
`bootloadHID` if you boot the board while holding down `8` (second from top, second from left, with usb plug is at the top) to keep it
|
||||||
|
in the bootloader:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ make jj40
|
||||||
|
$ bootloadHID -r jj4x4_default.hex
|
||||||
|
```
|
||||||
|
|
||||||
|
For Windows 10:
|
||||||
|
Windows sometimes doesn't recognize the jj4x4. The easiest way of flashing a new layout is probably using [HIDBootFlash](http://vusb.wikidot.com/project:hidbootflash).
|
||||||
|
1. Go to Windows Device Manager and find the keyboard (plug it in while holding down `8` (second from top, second from left, with usb plug is at the top)). It can be found under Human Interface Devices or under Keyboards.
|
||||||
|
2. Go to properties and the Details tab to find the hardware ID. You want the VID and the PID (code after the underscore). Plug them into HIDBootFlash and hit Find Device.
|
||||||
|
3. Use `make jj4x4:<keymap-name>` to generate the .hex file in the qmk basis folder. Select the .hex file in HIDBootFlash and press Flash Device.
|
||||||
|
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
1. Try plugging the board in while pressing `8` (usb plug at top, second from top, second from left). This will force it
|
||||||
|
to boot only the bootloader without loading the firmware. Once this is
|
||||||
|
done, just reflash the board with the original firmware.
|
||||||
|
2. Sometimes USB hubs can act weird, so try connecting the board directly
|
||||||
|
to your computer or plugging/unplugging the USB hub.
|
||||||
|
3. If you get an error such as "Resource Unavailable" when attemting to flash
|
||||||
|
on Linux, you may want to compile and run `tools/usb_detach.c`. See `tools/README.md`
|
||||||
|
for more info.
|
@ -0,0 +1,213 @@
|
|||||||
|
/**
|
||||||
|
* Backlighting code for PS2AVRGB boards (ATMEGA32A)
|
||||||
|
* Kenneth A. (github.com/krusli | krusli.me)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "backlight.h"
|
||||||
|
#include "quantum.h"
|
||||||
|
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
#include "backlight_custom.h"
|
||||||
|
#include "breathing_custom.h"
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// Port D: digital pins of the AVR chipset
|
||||||
|
#define NUMLOCK_PORT (1 << 0) // D0
|
||||||
|
#define CAPSLOCK_PORT (1 << 1) // D1
|
||||||
|
#define BACKLIGHT_PORT (1 << 4) // D4
|
||||||
|
#define SCROLLLOCK_PORT (1 << 6) // D6
|
||||||
|
|
||||||
|
#define TIMER_CLK_DIV64 0x03 ///< Timer clocked at F_CPU/64
|
||||||
|
#define TIMER1PRESCALE TIMER_CLK_DIV64 ///< timer 1 prescaler default
|
||||||
|
|
||||||
|
#define TIMER_PRESCALE_MASK 0x07 ///< Timer Prescaler Bit-Mask
|
||||||
|
|
||||||
|
#define PWM_MAX 0xFF
|
||||||
|
#define TIMER_TOP 255 // 8 bit PWM
|
||||||
|
|
||||||
|
extern backlight_config_t backlight_config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* References
|
||||||
|
* Port Registers: https://www.arduino.cc/en/Reference/PortManipulation
|
||||||
|
* TCCR1A: https://electronics.stackexchange.com/questions/92350/what-is-the-difference-between-tccr1a-and-tccr1b
|
||||||
|
* Timers: http://www.avrbeginners.net/architecture/timers/timers.html
|
||||||
|
* 16-bit timer setup: http://sculland.com/ATmega168/Interrupts-And-Timers/16-Bit-Timer-Setup/
|
||||||
|
* PS2AVRGB firmware: https://github.com/showjean/ps2avrU/tree/master/firmware
|
||||||
|
*/
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// turn LEDs on and off depending on USB caps/num/scroll lock states.
|
||||||
|
__attribute__ ((weak))
|
||||||
|
void led_set_user(uint8_t usb_led) {
|
||||||
|
if (usb_led & (1 << USB_LED_NUM_LOCK)) {
|
||||||
|
// turn on
|
||||||
|
DDRD |= NUMLOCK_PORT;
|
||||||
|
PORTD |= NUMLOCK_PORT;
|
||||||
|
} else {
|
||||||
|
// turn off
|
||||||
|
DDRD &= ~NUMLOCK_PORT;
|
||||||
|
PORTD &= ~NUMLOCK_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usb_led & (1 << USB_LED_CAPS_LOCK)) {
|
||||||
|
DDRD |= CAPSLOCK_PORT;
|
||||||
|
PORTD |= CAPSLOCK_PORT;
|
||||||
|
} else {
|
||||||
|
DDRD &= ~CAPSLOCK_PORT;
|
||||||
|
PORTD &= ~CAPSLOCK_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usb_led & (1 << USB_LED_SCROLL_LOCK)) {
|
||||||
|
DDRD |= SCROLLLOCK_PORT;
|
||||||
|
PORTD |= SCROLLLOCK_PORT;
|
||||||
|
} else {
|
||||||
|
DDRD &= ~SCROLLLOCK_PORT;
|
||||||
|
PORTD &= ~SCROLLLOCK_PORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef BACKLIGHT_ENABLE
|
||||||
|
|
||||||
|
// sets up Timer 1 for 8-bit PWM
|
||||||
|
void timer1PWMSetup(void) { // NOTE ONLY CALL THIS ONCE
|
||||||
|
// default 8 bit mode
|
||||||
|
TCCR1A &= ~(1 << 1); // cbi(TCCR1A,PWM11); <- set PWM11 bit to HIGH
|
||||||
|
TCCR1A |= (1 << 0); // sbi(TCCR1A,PWM10); <- set PWM10 bit to LOW
|
||||||
|
|
||||||
|
// clear output compare value A
|
||||||
|
// outb(OCR1AH, 0);
|
||||||
|
// outb(OCR1AL, 0);
|
||||||
|
|
||||||
|
// clear output comparator registers for B
|
||||||
|
OCR1BH = 0; // outb(OCR1BH, 0);
|
||||||
|
OCR1BL = 0; // outb(OCR1BL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_init = false;
|
||||||
|
void timer1Init(void) {
|
||||||
|
// timer1SetPrescaler(TIMER1PRESCALE)
|
||||||
|
// set to DIV/64
|
||||||
|
(TCCR1B) = ((TCCR1B) & ~TIMER_PRESCALE_MASK) | TIMER1PRESCALE;
|
||||||
|
|
||||||
|
// reset TCNT1
|
||||||
|
TCNT1H = 0; // outb(TCNT1H, 0);
|
||||||
|
TCNT1L = 0; // outb(TCNT1L, 0);
|
||||||
|
|
||||||
|
// TOIE1: Timer Overflow Interrupt Enable (Timer 1);
|
||||||
|
TIMSK |= _BV(TOIE1); // sbi(TIMSK, TOIE1);
|
||||||
|
|
||||||
|
is_init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timer1UnInit(void) {
|
||||||
|
// set prescaler back to NONE
|
||||||
|
(TCCR1B) = ((TCCR1B) & ~TIMER_PRESCALE_MASK) | 0x00; // TIMERRTC_CLK_STOP
|
||||||
|
|
||||||
|
// disable timer overflow interrupt
|
||||||
|
TIMSK &= ~_BV(TOIE1); // overflow bit?
|
||||||
|
|
||||||
|
setPWM(0);
|
||||||
|
|
||||||
|
is_init = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// handle TCNT1 overflow
|
||||||
|
//! Interrupt handler for tcnt1 overflow interrupt
|
||||||
|
ISR(TIMER1_OVF_vect, ISR_NOBLOCK)
|
||||||
|
{
|
||||||
|
// sei();
|
||||||
|
// handle breathing here
|
||||||
|
#ifdef BACKLIGHT_BREATHING
|
||||||
|
if (is_breathing()) {
|
||||||
|
custom_breathing_handler();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TODO call user defined function
|
||||||
|
}
|
||||||
|
|
||||||
|
// enable timer 1 PWM
|
||||||
|
// timer1PWMBOn()
|
||||||
|
void timer1PWMBEnable(void) {
|
||||||
|
// turn on channel B (OC1B) PWM output
|
||||||
|
// set OC1B as non-inverted PWM
|
||||||
|
TCCR1A |= _BV(COM1B1);
|
||||||
|
TCCR1A &= ~_BV(COM1B0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable timer 1 PWM
|
||||||
|
// timer1PWMBOff()
|
||||||
|
void timer1PWMBDisable(void) {
|
||||||
|
TCCR1A &= ~_BV(COM1B1);
|
||||||
|
TCCR1A &= ~_BV(COM1B0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void enableBacklight(void) {
|
||||||
|
DDRD |= BACKLIGHT_PORT; // set digital pin 4 as output
|
||||||
|
PORTD |= BACKLIGHT_PORT; // set digital pin 4 to high
|
||||||
|
}
|
||||||
|
|
||||||
|
void disableBacklight(void) {
|
||||||
|
// DDRD &= ~BACKLIGHT_PORT; // set digital pin 4 as input
|
||||||
|
PORTD &= ~BACKLIGHT_PORT; // set digital pin 4 to low
|
||||||
|
}
|
||||||
|
|
||||||
|
void startPWM(void) {
|
||||||
|
timer1Init();
|
||||||
|
timer1PWMBEnable();
|
||||||
|
enableBacklight();
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopPWM(void) {
|
||||||
|
timer1UnInit();
|
||||||
|
disableBacklight();
|
||||||
|
timer1PWMBDisable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void b_led_init_ports(void) {
|
||||||
|
/* turn backlight on/off depending on user preference */
|
||||||
|
#if BACKLIGHT_ON_STATE == 0
|
||||||
|
// DDRx register: sets the direction of Port D
|
||||||
|
// DDRD &= ~BACKLIGHT_PORT; // set digital pin 4 as input
|
||||||
|
PORTD &= ~BACKLIGHT_PORT; // set digital pin 4 to low
|
||||||
|
#else
|
||||||
|
DDRD |= BACKLIGHT_PORT; // set digital pin 4 as output
|
||||||
|
PORTD |= BACKLIGHT_PORT; // set digital pin 4 to high
|
||||||
|
#endif
|
||||||
|
|
||||||
|
timer1PWMSetup();
|
||||||
|
startPWM();
|
||||||
|
|
||||||
|
#ifdef BACKLIGHT_BREATHING
|
||||||
|
breathing_enable();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void b_led_set(uint8_t level) {
|
||||||
|
if (level > BACKLIGHT_LEVELS) {
|
||||||
|
level = BACKLIGHT_LEVELS;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPWM((int)(TIMER_TOP * (float) level / BACKLIGHT_LEVELS));
|
||||||
|
}
|
||||||
|
|
||||||
|
// called every matrix scan
|
||||||
|
void b_led_task(void) {
|
||||||
|
// do nothing for now
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPWM(uint16_t xValue) {
|
||||||
|
if (xValue > TIMER_TOP) {
|
||||||
|
xValue = TIMER_TOP;
|
||||||
|
}
|
||||||
|
OCR1B = xValue; // timer1PWMBSet(xValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BACKLIGHT_ENABLE
|
@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* Backlighting code for PS2AVRGB boards (ATMEGA32A)
|
||||||
|
* Kenneth A. (github.com/krusli | krusli.me)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BACKLIGHT_CUSTOM_H
|
||||||
|
#define BACKLIGHT_CUSTOM_H
|
||||||
|
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
void b_led_init_ports(void);
|
||||||
|
void b_led_set(uint8_t level);
|
||||||
|
void b_led_task(void);
|
||||||
|
void setPWM(uint16_t xValue);
|
||||||
|
|
||||||
|
#endif // BACKLIGHT_CUSTOM_H
|
@ -0,0 +1,140 @@
|
|||||||
|
/**
|
||||||
|
* Breathing effect code for PS2AVRGB boards (ATMEGA32A)
|
||||||
|
* Works in conjunction with `backlight.c`.
|
||||||
|
*
|
||||||
|
* Code adapted from `quantum.c` to register with the existing TIMER1 overflow
|
||||||
|
* handler in `backlight.c` instead of setting up its own timer.
|
||||||
|
* Kenneth A. (github.com/krusli | krusli.me)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef BACKLIGHT_ENABLE
|
||||||
|
#ifdef BACKLIGHT_BREATHING
|
||||||
|
|
||||||
|
#include "backlight_custom.h"
|
||||||
|
|
||||||
|
#ifndef BREATHING_PERIOD
|
||||||
|
#define BREATHING_PERIOD 6
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define breathing_min() do {breathing_counter = 0;} while (0)
|
||||||
|
#define breathing_max() do {breathing_counter = breathing_period * 244 / 2;} while (0)
|
||||||
|
|
||||||
|
// TODO make this share code with quantum.c
|
||||||
|
|
||||||
|
#define BREATHING_NO_HALT 0
|
||||||
|
#define BREATHING_HALT_OFF 1
|
||||||
|
#define BREATHING_HALT_ON 2
|
||||||
|
#define BREATHING_STEPS 128
|
||||||
|
|
||||||
|
static uint8_t breathing_period = BREATHING_PERIOD;
|
||||||
|
static uint8_t breathing_halt = BREATHING_NO_HALT;
|
||||||
|
static uint16_t breathing_counter = 0;
|
||||||
|
|
||||||
|
static bool breathing = false;
|
||||||
|
|
||||||
|
bool is_breathing(void) {
|
||||||
|
return breathing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See http://jared.geek.nz/2013/feb/linear-led-pwm
|
||||||
|
static uint16_t cie_lightness(uint16_t v) {
|
||||||
|
if (v <= 5243) // if below 8% of max
|
||||||
|
return v / 9; // same as dividing by 900%
|
||||||
|
else {
|
||||||
|
uint32_t y = (((uint32_t) v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
|
||||||
|
// to get a useful result with integer division, we shift left in the expression above
|
||||||
|
// and revert what we've done again after squaring.
|
||||||
|
y = y * y * y >> 8;
|
||||||
|
if (y > 0xFFFFUL) // prevent overflow
|
||||||
|
return 0xFFFFU;
|
||||||
|
else
|
||||||
|
return (uint16_t) y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_enable(void) {
|
||||||
|
breathing = true;
|
||||||
|
breathing_counter = 0;
|
||||||
|
breathing_halt = BREATHING_NO_HALT;
|
||||||
|
// interrupt already registered
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_pulse(void) {
|
||||||
|
if (get_backlight_level() == 0)
|
||||||
|
breathing_min();
|
||||||
|
else
|
||||||
|
breathing_max();
|
||||||
|
breathing_halt = BREATHING_HALT_ON;
|
||||||
|
// breathing_interrupt_enable();
|
||||||
|
breathing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_disable(void) {
|
||||||
|
breathing = false;
|
||||||
|
// backlight_set(get_backlight_level());
|
||||||
|
b_led_set(get_backlight_level()); // custom implementation of backlight_set()
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_self_disable(void)
|
||||||
|
{
|
||||||
|
if (get_backlight_level() == 0)
|
||||||
|
breathing_halt = BREATHING_HALT_OFF;
|
||||||
|
else
|
||||||
|
breathing_halt = BREATHING_HALT_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_toggle(void) {
|
||||||
|
if (is_breathing())
|
||||||
|
breathing_disable();
|
||||||
|
else
|
||||||
|
breathing_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_period_set(uint8_t value)
|
||||||
|
{
|
||||||
|
if (!value)
|
||||||
|
value = 1;
|
||||||
|
breathing_period = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_period_default(void) {
|
||||||
|
breathing_period_set(BREATHING_PERIOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_period_inc(void)
|
||||||
|
{
|
||||||
|
breathing_period_set(breathing_period+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_period_dec(void)
|
||||||
|
{
|
||||||
|
breathing_period_set(breathing_period-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To generate breathing curve in python:
|
||||||
|
* from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)]
|
||||||
|
*/
|
||||||
|
static const uint8_t breathing_table[BREATHING_STEPS] PROGMEM = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 17, 20, 24, 28, 32, 36, 41, 46, 51, 57, 63, 70, 76, 83, 91, 98, 106, 113, 121, 129, 138, 146, 154, 162, 170, 178, 185, 193, 200, 207, 213, 220, 225, 231, 235, 240, 244, 247, 250, 252, 253, 254, 255, 254, 253, 252, 250, 247, 244, 240, 235, 231, 225, 220, 213, 207, 200, 193, 185, 178, 170, 162, 154, 146, 138, 129, 121, 113, 106, 98, 91, 83, 76, 70, 63, 57, 51, 46, 41, 36, 32, 28, 24, 20, 17, 15, 12, 10, 8, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
// Use this before the cie_lightness function.
|
||||||
|
static inline uint16_t scale_backlight(uint16_t v) {
|
||||||
|
return v / BACKLIGHT_LEVELS * get_backlight_level();
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_breathing_handler(void) {
|
||||||
|
uint16_t interval = (uint16_t) breathing_period * 244 / BREATHING_STEPS;
|
||||||
|
// resetting after one period to prevent ugly reset at overflow.
|
||||||
|
breathing_counter = (breathing_counter + 1) % (breathing_period * 244);
|
||||||
|
uint8_t index = breathing_counter / interval % BREATHING_STEPS;
|
||||||
|
|
||||||
|
if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) ||
|
||||||
|
((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1)))
|
||||||
|
{
|
||||||
|
// breathing_interrupt_disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
setPWM(cie_lightness(scale_backlight((uint16_t) pgm_read_byte(&breathing_table[index]) * 0x0101U)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BACKLIGHT_BREATHING
|
||||||
|
#endif // BACKLIGHT_ENABLE
|
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 Luiz Ribeiro <luizribeiro@gmail.com>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config_common.h"
|
||||||
|
|
||||||
|
#ifndef CONFIG_H
|
||||||
|
#define CONFIG_H
|
||||||
|
|
||||||
|
#define VENDOR_ID 0x20A0
|
||||||
|
#define PRODUCT_ID 0x422D
|
||||||
|
// TODO: share these strings with usbconfig.h
|
||||||
|
// Edit usbconfig.h to change these.
|
||||||
|
#define MANUFACTURER Kprepublic
|
||||||
|
#define PRODUCT jj4x4
|
||||||
|
|
||||||
|
/* matrix size */
|
||||||
|
#define MATRIX_ROWS 4
|
||||||
|
#define MATRIX_COLS 4
|
||||||
|
#define MATRIX_ROW_PINS { B5, B0, B3, B4 }
|
||||||
|
#define MATRIX_COL_PINS { A1, A0, A2, A3 }
|
||||||
|
|
||||||
|
/* COL2ROW or ROW2COL */
|
||||||
|
#define DIODE_DIRECTION COL2ROW
|
||||||
|
|
||||||
|
#define BACKLIGHT_LEVELS 12
|
||||||
|
// #define BACKLIGHT_BREATHING // works, but BL_TOGG might not work
|
||||||
|
|
||||||
|
#define TAPPING_TOGGLE 3
|
||||||
|
|
||||||
|
#define NO_UART 1
|
||||||
|
|
||||||
|
/* RGB underglow */
|
||||||
|
// The RGB_DI_PIN value seems to be shared between all PS2AVRGB boards.
|
||||||
|
// The same pin is used on the JJ40, at least.
|
||||||
|
#define RGBLED_NUM 5
|
||||||
|
#define RGB_DI_PIN E2 // NOTE: for PS2AVRGB boards, underglow commands are sent via I2C to 0xB0.
|
||||||
|
#define RGBLIGHT_ANIMATIONS
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 Luiz Ribeiro <luizribeiro@gmail.com>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <util/twi.h>
|
||||||
|
|
||||||
|
#include "i2c.h"
|
||||||
|
|
||||||
|
void i2c_set_bitrate(uint16_t bitrate_khz) {
|
||||||
|
uint8_t bitrate_div = ((F_CPU / 1000l) / bitrate_khz);
|
||||||
|
if (bitrate_div >= 16) {
|
||||||
|
bitrate_div = (bitrate_div - 16) / 2;
|
||||||
|
}
|
||||||
|
TWBR = bitrate_div;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2c_init(void) {
|
||||||
|
// set pull-up resistors on I2C bus pins
|
||||||
|
PORTC |= 0b11;
|
||||||
|
|
||||||
|
i2c_set_bitrate(400);
|
||||||
|
|
||||||
|
// enable TWI (two-wire interface)
|
||||||
|
TWCR |= (1 << TWEN);
|
||||||
|
|
||||||
|
// enable TWI interrupt and slave address ACK
|
||||||
|
TWCR |= (1 << TWIE);
|
||||||
|
TWCR |= (1 << TWEA);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t i2c_start(uint8_t address) {
|
||||||
|
// reset TWI control register
|
||||||
|
TWCR = 0;
|
||||||
|
|
||||||
|
// begin transmission and wait for it to end
|
||||||
|
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
|
||||||
|
while (!(TWCR & (1<<TWINT)));
|
||||||
|
|
||||||
|
// check if the start condition was successfully transmitted
|
||||||
|
if ((TWSR & 0xF8) != TW_START) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// transmit address and wait
|
||||||
|
TWDR = address;
|
||||||
|
TWCR = (1<<TWINT) | (1<<TWEN);
|
||||||
|
while (!(TWCR & (1<<TWINT)));
|
||||||
|
|
||||||
|
// check if the device has acknowledged the READ / WRITE mode
|
||||||
|
uint8_t twst = TW_STATUS & 0xF8;
|
||||||
|
if ((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2c_stop(void) {
|
||||||
|
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t i2c_write(uint8_t data) {
|
||||||
|
TWDR = data;
|
||||||
|
|
||||||
|
// transmit data and wait
|
||||||
|
TWCR = (1<<TWINT) | (1<<TWEN);
|
||||||
|
while (!(TWCR & (1<<TWINT)));
|
||||||
|
|
||||||
|
if ((TWSR & 0xF8) != TW_MT_DATA_ACK) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t i2c_send(uint8_t address, uint8_t *data, uint16_t length) {
|
||||||
|
if (i2c_start(address)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < length; i++) {
|
||||||
|
if (i2c_write(data[i])) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_stop();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 Luiz Ribeiro <luizribeiro@gmail.com>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __I2C_H__
|
||||||
|
#define __I2C_H__
|
||||||
|
|
||||||
|
void i2c_init(void);
|
||||||
|
void i2c_set_bitrate(uint16_t bitrate_khz);
|
||||||
|
uint8_t i2c_send(uint8_t address, uint8_t *data, uint16_t length);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"keyboard_name": "jj40",
|
||||||
|
"url": "",
|
||||||
|
"maintainer": "qmk",
|
||||||
|
"width": 12,
|
||||||
|
"height": 4,
|
||||||
|
"layouts": {
|
||||||
|
"LAYOUT_planck_mit": {
|
||||||
|
"key_count": 47,
|
||||||
|
"layout": [{"x":0, "y":0}, {"x":1, "y":0}, {"x":2, "y":0}, {"x":3, "y":0}, {"x":4, "y":0}, {"x":5, "y":0}, {"x":6, "y":0}, {"x":7, "y":0}, {"x":8, "y":0}, {"x":9, "y":0}, {"x":10, "y":0}, {"x":11, "y":0}, {"x":0, "y":1}, {"x":1, "y":1}, {"x":2, "y":1}, {"x":3, "y":1}, {"x":4, "y":1}, {"x":5, "y":1}, {"x":6, "y":1}, {"x":7, "y":1}, {"x":8, "y":1}, {"x":9, "y":1}, {"x":10, "y":1}, {"x":11, "y":1}, {"x":0, "y":2}, {"x":1, "y":2}, {"x":2, "y":2}, {"x":3, "y":2}, {"x":4, "y":2}, {"x":5, "y":2}, {"x":6, "y":2}, {"x":7, "y":2}, {"x":8, "y":2}, {"x":9, "y":2}, {"x":10, "y":2}, {"x":11, "y":2}, {"x":0, "y":3}, {"x":1, "y":3}, {"x":2, "y":3}, {"x":3, "y":3}, {"x":4, "y":3}, {"x":5, "y":3, "w":2}, {"x":7, "y":3}, {"x":8, "y":3}, {"x":9, "y":3}, {"x":10, "y":3}, {"x":11, "y":3}]
|
||||||
|
},
|
||||||
|
|
||||||
|
"LAYOUT_ortho_4x12": {
|
||||||
|
"key_count": 48,
|
||||||
|
"layout": [{"x":0, "y":0}, {"x":1, "y":0}, {"x":2, "y":0}, {"x":3, "y":0}, {"x":4, "y":0}, {"x":5, "y":0}, {"x":6, "y":0}, {"x":7, "y":0}, {"x":8, "y":0}, {"x":9, "y":0}, {"x":10, "y":0}, {"x":11, "y":0}, {"x":0, "y":1}, {"x":1, "y":1}, {"x":2, "y":1}, {"x":3, "y":1}, {"x":4, "y":1}, {"x":5, "y":1}, {"x":6, "y":1}, {"x":7, "y":1}, {"x":8, "y":1}, {"x":9, "y":1}, {"x":10, "y":1}, {"x":11, "y":1}, {"x":0, "y":2}, {"x":1, "y":2}, {"x":2, "y":2}, {"x":3, "y":2}, {"x":4, "y":2}, {"x":5, "y":2}, {"x":6, "y":2}, {"x":7, "y":2}, {"x":8, "y":2}, {"x":9, "y":2}, {"x":10, "y":2}, {"x":11, "y":2}, {"x":0, "y":3}, {"x":1, "y":3}, {"x":2, "y":3}, {"x":3, "y":3}, {"x":4, "y":3}, {"x":5, "y":3}, {"x":6, "y":3}, {"x":7, "y":3}, {"x":8, "y":3}, {"x":9, "y":3}, {"x":10, "y":3}, {"x":11, "y":3}]
|
||||||
|
},
|
||||||
|
|
||||||
|
"LAYOUT_planck_1x2uR": {
|
||||||
|
"key_count": 47,
|
||||||
|
"layout": [{"x":0, "y":0}, {"x":1, "y":0}, {"x":2, "y":0}, {"x":3, "y":0}, {"x":4, "y":0}, {"x":5, "y":0}, {"x":6, "y":0}, {"x":7, "y":0}, {"x":8, "y":0}, {"x":9, "y":0}, {"x":10, "y":0}, {"x":11, "y":0}, {"x":0, "y":1}, {"x":1, "y":1}, {"x":2, "y":1}, {"x":3, "y":1}, {"x":4, "y":1}, {"x":5, "y":1}, {"x":6, "y":1}, {"x":7, "y":1}, {"x":8, "y":1}, {"x":9, "y":1}, {"x":10, "y":1}, {"x":11, "y":1}, {"x":0, "y":2}, {"x":1, "y":2}, {"x":2, "y":2}, {"x":3, "y":2}, {"x":4, "y":2}, {"x":5, "y":2}, {"x":6, "y":2}, {"x":7, "y":2}, {"x":8, "y":2}, {"x":9, "y":2}, {"x":10, "y":2}, {"x":11, "y":2}, {"x":0, "y":3}, {"x":1, "y":3}, {"x":2, "y":3}, {"x":3, "y":3}, {"x":4, "y":3}, {"x":5, "y":3}, {"x":6, "y":3, "w":2}, {"x":8, "y":3}, {"x":9, "y":3}, {"x":10, "y":3}, {"x":11, "y":3}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 Luiz Ribeiro <luizribeiro@gmail.com>
|
||||||
|
Modified 2018 Kenneth A. <github.com/krusli>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jj4x4.h"
|
||||||
|
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
#include "action_layer.h"
|
||||||
|
#include "quantum.h"
|
||||||
|
|
||||||
|
#include "i2c.h"
|
||||||
|
|
||||||
|
#include "backlight.h"
|
||||||
|
#include "backlight_custom.h"
|
||||||
|
|
||||||
|
// for keyboard subdirectory level init functions
|
||||||
|
// @Override
|
||||||
|
void matrix_init_kb(void) {
|
||||||
|
// call user level keymaps, if any
|
||||||
|
matrix_init_user();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef BACKLIGHT_ENABLE
|
||||||
|
/// Overrides functions in `quantum.c`
|
||||||
|
void backlight_init_ports(void) {
|
||||||
|
b_led_init_ports();
|
||||||
|
}
|
||||||
|
|
||||||
|
void backlight_task(void) {
|
||||||
|
b_led_task();
|
||||||
|
}
|
||||||
|
|
||||||
|
void backlight_set(uint8_t level) {
|
||||||
|
b_led_set(level);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RGBLIGHT_ENABLE
|
||||||
|
extern rgblight_config_t rgblight_config;
|
||||||
|
|
||||||
|
// custom RGB driver
|
||||||
|
void rgblight_set(void) {
|
||||||
|
if (!rgblight_config.enable) {
|
||||||
|
for (uint8_t i=0; i<RGBLED_NUM; i++) {
|
||||||
|
led[i].r = 0;
|
||||||
|
led[i].g = 0;
|
||||||
|
led[i].b = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_init();
|
||||||
|
i2c_send(0xb0, (uint8_t*)led, 3 * RGBLED_NUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rgb_init = false;
|
||||||
|
|
||||||
|
void matrix_scan_kb(void) {
|
||||||
|
// if LEDs were previously on before poweroff, turn them back on
|
||||||
|
if (rgb_init == false && rgblight_config.enable) {
|
||||||
|
i2c_init();
|
||||||
|
i2c_send(0xb0, (uint8_t*)led, 3 * RGBLED_NUM);
|
||||||
|
rgb_init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
rgblight_task();
|
||||||
|
#else
|
||||||
|
void matrix_scan_kb(void) {
|
||||||
|
#endif
|
||||||
|
matrix_scan_user();
|
||||||
|
/* Nothing else for now. */
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) // overridable
|
||||||
|
void matrix_init_user(void) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__((weak)) // overridable
|
||||||
|
void matrix_scan_user(void) {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 Luiz Ribeiro <luizribeiro@gmail.com>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KEYMAP_COMMON_H
|
||||||
|
#define KEYMAP_COMMON_H
|
||||||
|
|
||||||
|
#include "quantum.h"
|
||||||
|
#include "quantum_keycodes.h"
|
||||||
|
#include "keycode.h"
|
||||||
|
#include "action.h"
|
||||||
|
|
||||||
|
void matrix_init_user(void); // TODO port this to other PS2AVRGB boards
|
||||||
|
|
||||||
|
#define XXX KC_NO
|
||||||
|
|
||||||
|
|
||||||
|
#define LAYOUT( \
|
||||||
|
K01, K02, K03, K04, \
|
||||||
|
K11, K12, K13, K14, \
|
||||||
|
K21, K22, K23, K24, \
|
||||||
|
K31, K32, K33, K34 \
|
||||||
|
) \
|
||||||
|
{ \
|
||||||
|
{ K01, K02, K03, K04 }, \
|
||||||
|
{ K11, K12, K13, K14 }, \
|
||||||
|
{ K21, K22, K23, K24 }, \
|
||||||
|
{ K31, K32, K33, K34 } \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,34 @@
|
|||||||
|
#include QMK_KEYBOARD_H
|
||||||
|
|
||||||
|
|
||||||
|
#define _QWERTY 0
|
||||||
|
|
||||||
|
|
||||||
|
enum custom_keycodes {
|
||||||
|
QWERTY = SAFE_RANGE,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
/* Qwerty
|
||||||
|
* ,---------------------------.
|
||||||
|
* | A | B | C | D |
|
||||||
|
* +------+------+------+------|
|
||||||
|
* | E | F | G | H |
|
||||||
|
* +------+------+------+------|
|
||||||
|
* | I | J | K | L |
|
||||||
|
* +------+------+------+------|
|
||||||
|
* | M | N | O | P |
|
||||||
|
* ----------------------------'
|
||||||
|
*/
|
||||||
|
[_QWERTY] = LAYOUT( \
|
||||||
|
KC_A, KC_B, KC_C, KC_D, \
|
||||||
|
KC_E, KC_F, KC_G, KC_H, \
|
||||||
|
KC_I, KC_J, KC_K, KC_L, \
|
||||||
|
KC_M, KC_N, KC_O, KC_P \
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Loop
|
||||||
|
void matrix_scan_user(void) {
|
||||||
|
// Empty
|
||||||
|
};
|
@ -0,0 +1,58 @@
|
|||||||
|
# Copyright 2017 Luiz Ribeiro <luizribeiro@gmail.com>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# MCU name
|
||||||
|
MCU = atmega32a
|
||||||
|
PROTOCOL = VUSB
|
||||||
|
|
||||||
|
# unsupported features for now
|
||||||
|
NO_UART = yes
|
||||||
|
NO_SUSPEND_POWER_DOWN = yes
|
||||||
|
|
||||||
|
# processor frequency
|
||||||
|
F_CPU = 12000000
|
||||||
|
|
||||||
|
# Bootloader
|
||||||
|
# This definition is optional, and if your keyboard supports multiple bootloaders of
|
||||||
|
# different sizes, comment this out, and the correct address will be loaded
|
||||||
|
# automatically (+60). See bootloader.mk for all options.
|
||||||
|
BOOTLOADER = bootloadHID
|
||||||
|
|
||||||
|
# build options
|
||||||
|
BOOTMAGIC_ENABLE = no
|
||||||
|
MOUSEKEY_ENABLE = no
|
||||||
|
EXTRAKEY_ENABLE = yes
|
||||||
|
CONSOLE_ENABLE = no
|
||||||
|
COMMAND_ENABLE = yes
|
||||||
|
|
||||||
|
BACKLIGHT_ENABLE = yes
|
||||||
|
BACKLIGHT_CUSTOM_DRIVER = yes
|
||||||
|
|
||||||
|
RGBLIGHT_ENABLE = yes
|
||||||
|
RGBLIGHT_CUSTOM_DRIVER = yes
|
||||||
|
|
||||||
|
KEY_LOCK_ENABLE = yes
|
||||||
|
|
||||||
|
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
|
||||||
|
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
|
||||||
|
|
||||||
|
OPT_DEFS = -DDEBUG_LEVEL=0
|
||||||
|
|
||||||
|
SRC = i2c.c backlight.c
|
||||||
|
|
||||||
|
# programming options
|
||||||
|
PROGRAM_CMD = ./util/atmega32a_program.py $(TARGET).hex
|
||||||
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
|||||||
|
# JJ40 Tools
|
||||||
|
|
||||||
|
## usb_detach.c
|
||||||
|
|
||||||
|
When trying to flash on Linux, you may encounter a "Resource Unavailable" error. This means that Linux's HID driver has taken exclusive control of the keyboard, and the program script can't flash it.
|
||||||
|
This program can force Linux to give up a device, so that the programming script can reset it.
|
||||||
|
|
||||||
|
### To compile:
|
||||||
|
```
|
||||||
|
gcc usb_detach.c -o usb_detach
|
||||||
|
```
|
||||||
|
|
||||||
|
### To run:
|
||||||
|
1. Use `lsusb` to discover the Bus and Device numbers for your keyboard.
|
||||||
|
2. Run the program: `sudo ./usb_detach /dev/bus/usb/<BUS>/<DEVICE>`.
|
||||||
|
3. Build and program the firmware as normal.
|
@ -0,0 +1,33 @@
|
|||||||
|
/* Found at https://www.linuxquestions.org/questions/linux-hardware-18/how-to-unclaim-usb-device-558138/#post3406986 */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/ioctl.h>
|
||||||
|
#include <linux/usbdevice_fs.h>
|
||||||
|
|
||||||
|
int main(int argc, char**argv)
|
||||||
|
{
|
||||||
|
struct usbdevfs_ioctl command;
|
||||||
|
int ret;
|
||||||
|
int fd;
|
||||||
|
int i;
|
||||||
|
if (argc>1) {
|
||||||
|
fd = open(argv[1],O_RDWR);
|
||||||
|
if (fd<1){
|
||||||
|
perror("unable to open file");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
for (i=0;i<255;i++){ // hack: should fetch how many interface there is.
|
||||||
|
command.ifno = i;
|
||||||
|
command.ioctl_code = USBDEVFS_DISCONNECT;
|
||||||
|
command.data = NULL;
|
||||||
|
ret = ioctl(fd, USBDEVFS_IOCTL, &command);
|
||||||
|
if(ret!=-1)
|
||||||
|
printf("un claimed interface %d %d\n",i,ret);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf ("usage: %s /dev/bus/usb/BUS/DEVICE\n",argv[0]);
|
||||||
|
printf("Release all interfaces of this usb device for usage in virtualisation\n");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,397 @@
|
|||||||
|
/* Name: usbconfig.h
|
||||||
|
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2005-04-01
|
||||||
|
* Tabsize: 4
|
||||||
|
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||||
|
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||||
|
* This Revision: $Id: usbconfig-prototype.h 785 2010-05-30 17:57:07Z cs $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __usbconfig_h_included__
|
||||||
|
#define __usbconfig_h_included__
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
General Description:
|
||||||
|
This file is an example configuration (with inline documentation) for the USB
|
||||||
|
driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is
|
||||||
|
also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may
|
||||||
|
wire the lines to any other port, as long as D+ is also wired to INT0 (or any
|
||||||
|
other hardware interrupt, as long as it is the highest level interrupt, see
|
||||||
|
section at the end of this file).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ---------------------------- Hardware Config ---------------------------- */
|
||||||
|
|
||||||
|
#define USB_CFG_IOPORTNAME D
|
||||||
|
/* This is the port where the USB bus is connected. When you configure it to
|
||||||
|
* "B", the registers PORTB, PINB and DDRB will be used.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DMINUS_BIT 3
|
||||||
|
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
|
||||||
|
* This may be any bit in the port.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DPLUS_BIT 2
|
||||||
|
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
|
||||||
|
* This may be any bit in the port. Please note that D+ must also be connected
|
||||||
|
* to interrupt pin INT0! [You can also use other interrupts, see section
|
||||||
|
* "Optional MCU Description" below, or you can connect D- to the interrupt, as
|
||||||
|
* it is required if you use the USB_COUNT_SOF feature. If you use D- for the
|
||||||
|
* interrupt, the USB interrupt will also be triggered at Start-Of-Frame
|
||||||
|
* markers every millisecond.]
|
||||||
|
*/
|
||||||
|
#define USB_CFG_CLOCK_KHZ (F_CPU/1000)
|
||||||
|
/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000,
|
||||||
|
* 16500, 18000 and 20000. The 12.8 MHz and 16.5 MHz versions of the code
|
||||||
|
* require no crystal, they tolerate +/- 1% deviation from the nominal
|
||||||
|
* frequency. All other rates require a precision of 2000 ppm and thus a
|
||||||
|
* crystal!
|
||||||
|
* Since F_CPU should be defined to your actual clock rate anyway, you should
|
||||||
|
* not need to modify this setting.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_CHECK_CRC 0
|
||||||
|
/* Define this to 1 if you want that the driver checks integrity of incoming
|
||||||
|
* data packets (CRC checks). CRC checks cost quite a bit of code size and are
|
||||||
|
* currently only available for 18 MHz crystal clock. You must choose
|
||||||
|
* USB_CFG_CLOCK_KHZ = 18000 if you enable this option.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ----------------------- Optional Hardware Config ------------------------ */
|
||||||
|
|
||||||
|
/* #define USB_CFG_PULLUP_IOPORTNAME D */
|
||||||
|
/* If you connect the 1.5k pullup resistor from D- to a port pin instead of
|
||||||
|
* V+, you can connect and disconnect the device from firmware by calling
|
||||||
|
* the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h).
|
||||||
|
* This constant defines the port on which the pullup resistor is connected.
|
||||||
|
*/
|
||||||
|
/* #define USB_CFG_PULLUP_BIT 4 */
|
||||||
|
/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined
|
||||||
|
* above) where the 1.5k pullup resistor is connected. See description
|
||||||
|
* above for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* --------------------------- Functional Range ---------------------------- */
|
||||||
|
|
||||||
|
#define USB_CFG_HAVE_INTRIN_ENDPOINT 1
|
||||||
|
/* Define this to 1 if you want to compile a version with two endpoints: The
|
||||||
|
* default control endpoint 0 and an interrupt-in endpoint (any other endpoint
|
||||||
|
* number).
|
||||||
|
*/
|
||||||
|
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 1
|
||||||
|
/* Define this to 1 if you want to compile a version with three endpoints: The
|
||||||
|
* default control endpoint 0, an interrupt-in endpoint 3 (or the number
|
||||||
|
* configured below) and a catch-all default interrupt-in endpoint as above.
|
||||||
|
* You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_EP3_NUMBER 3
|
||||||
|
/* If the so-called endpoint 3 is used, it can now be configured to any other
|
||||||
|
* endpoint number (except 0) with this macro. Default if undefined is 3.
|
||||||
|
*/
|
||||||
|
/* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */
|
||||||
|
/* The above macro defines the startup condition for data toggling on the
|
||||||
|
* interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1.
|
||||||
|
* Since the token is toggled BEFORE sending any data, the first packet is
|
||||||
|
* sent with the oposite value of this configuration!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_HALT 0
|
||||||
|
/* Define this to 1 if you also want to implement the ENDPOINT_HALT feature
|
||||||
|
* for endpoint 1 (interrupt endpoint). Although you may not need this feature,
|
||||||
|
* it is required by the standard. We have made it a config option because it
|
||||||
|
* bloats the code considerably.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_SUPPRESS_INTR_CODE 0
|
||||||
|
/* Define this to 1 if you want to declare interrupt-in endpoints, but don't
|
||||||
|
* want to send any data over them. If this macro is defined to 1, functions
|
||||||
|
* usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if
|
||||||
|
* you need the interrupt-in endpoints in order to comply to an interface
|
||||||
|
* (e.g. HID), but never want to send any data. This option saves a couple
|
||||||
|
* of bytes in flash memory and the transmit buffers in RAM.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_INTR_POLL_INTERVAL 1
|
||||||
|
/* If you compile a version with endpoint 1 (interrupt-in), this is the poll
|
||||||
|
* interval. The value is in milliseconds and must not be less than 10 ms for
|
||||||
|
* low speed devices.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IS_SELF_POWERED 0
|
||||||
|
/* Define this to 1 if the device has its own power supply. Set it to 0 if the
|
||||||
|
* device is powered from the USB bus.
|
||||||
|
*/
|
||||||
|
// max power draw with maxed white underglow measured at 120 mA (peaks)
|
||||||
|
#define USB_CFG_MAX_BUS_POWER 100
|
||||||
|
/* Set this variable to the maximum USB bus power consumption of your device.
|
||||||
|
* The value is in milliamperes. [It will be divided by two since USB
|
||||||
|
* communicates power requirements in units of 2 mA.]
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_FN_WRITE 1
|
||||||
|
/* Set this to 1 if you want usbFunctionWrite() to be called for control-out
|
||||||
|
* transfers. Set it to 0 if you don't need it and want to save a couple of
|
||||||
|
* bytes.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_FN_READ 0
|
||||||
|
/* Set this to 1 if you need to send control replies which are generated
|
||||||
|
* "on the fly" when usbFunctionRead() is called. If you only want to send
|
||||||
|
* data from a static buffer, set it to 0 and return the data from
|
||||||
|
* usbFunctionSetup(). This saves a couple of bytes.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_FN_WRITEOUT 0
|
||||||
|
/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints.
|
||||||
|
* You must implement the function usbFunctionWriteOut() which receives all
|
||||||
|
* interrupt/bulk data sent to any endpoint other than 0. The endpoint number
|
||||||
|
* can be found in 'usbRxToken'.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_HAVE_FLOWCONTROL 0
|
||||||
|
/* Define this to 1 if you want flowcontrol over USB data. See the definition
|
||||||
|
* of the macros usbDisableAllRequests() and usbEnableAllRequests() in
|
||||||
|
* usbdrv.h.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DRIVER_FLASH_PAGE 0
|
||||||
|
/* If the device has more than 64 kBytes of flash, define this to the 64 k page
|
||||||
|
* where the driver's constants (descriptors) are located. Or in other words:
|
||||||
|
* Define this to 1 for boot loaders on the ATMega128.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_LONG_TRANSFERS 0
|
||||||
|
/* Define this to 1 if you want to send/receive blocks of more than 254 bytes
|
||||||
|
* in a single control-in or control-out transfer. Note that the capability
|
||||||
|
* for long transfers increases the driver size.
|
||||||
|
*/
|
||||||
|
/* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */
|
||||||
|
/* This macro is a hook if you want to do unconventional things. If it is
|
||||||
|
* defined, it's inserted at the beginning of received message processing.
|
||||||
|
* If you eat the received message and don't want default processing to
|
||||||
|
* proceed, do a return after doing your things. One possible application
|
||||||
|
* (besides debugging) is to flash a status LED on each packet.
|
||||||
|
*/
|
||||||
|
/* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */
|
||||||
|
/* This macro is a hook if you need to know when an USB RESET occurs. It has
|
||||||
|
* one parameter which distinguishes between the start of RESET state and its
|
||||||
|
* end.
|
||||||
|
*/
|
||||||
|
/* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned(); */
|
||||||
|
/* This macro (if defined) is executed when a USB SET_ADDRESS request was
|
||||||
|
* received.
|
||||||
|
*/
|
||||||
|
#define USB_COUNT_SOF 1
|
||||||
|
/* define this macro to 1 if you need the global variable "usbSofCount" which
|
||||||
|
* counts SOF packets. This feature requires that the hardware interrupt is
|
||||||
|
* connected to D- instead of D+.
|
||||||
|
*/
|
||||||
|
/* #ifdef __ASSEMBLER__
|
||||||
|
* macro myAssemblerMacro
|
||||||
|
* in YL, TCNT0
|
||||||
|
* sts timer0Snapshot, YL
|
||||||
|
* endm
|
||||||
|
* #endif
|
||||||
|
* #define USB_SOF_HOOK myAssemblerMacro
|
||||||
|
* This macro (if defined) is executed in the assembler module when a
|
||||||
|
* Start Of Frame condition is detected. It is recommended to define it to
|
||||||
|
* the name of an assembler macro which is defined here as well so that more
|
||||||
|
* than one assembler instruction can be used. The macro may use the register
|
||||||
|
* YL and modify SREG. If it lasts longer than a couple of cycles, USB messages
|
||||||
|
* immediately after an SOF pulse may be lost and must be retried by the host.
|
||||||
|
* What can you do with this hook? Since the SOF signal occurs exactly every
|
||||||
|
* 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in
|
||||||
|
* designs running on the internal RC oscillator.
|
||||||
|
* Please note that Start Of Frame detection works only if D- is wired to the
|
||||||
|
* interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_CHECK_DATA_TOGGLING 0
|
||||||
|
/* define this macro to 1 if you want to filter out duplicate data packets
|
||||||
|
* sent by the host. Duplicates occur only as a consequence of communication
|
||||||
|
* errors, when the host does not receive an ACK. Please note that you need to
|
||||||
|
* implement the filtering yourself in usbFunctionWriteOut() and
|
||||||
|
* usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable
|
||||||
|
* for each control- and out-endpoint to check for duplicate packets.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0
|
||||||
|
/* define this macro to 1 if you want the function usbMeasureFrameLength()
|
||||||
|
* compiled in. This function can be used to calibrate the AVR's RC oscillator.
|
||||||
|
*/
|
||||||
|
#define USB_USE_FAST_CRC 0
|
||||||
|
/* The assembler module has two implementations for the CRC algorithm. One is
|
||||||
|
* faster, the other is smaller. This CRC routine is only used for transmitted
|
||||||
|
* messages where timing is not critical. The faster routine needs 31 cycles
|
||||||
|
* per byte while the smaller one needs 61 to 69 cycles. The faster routine
|
||||||
|
* may be worth the 32 bytes bigger code size if you transmit lots of data and
|
||||||
|
* run the AVR close to its limit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -------------------------- Device Description --------------------------- */
|
||||||
|
|
||||||
|
#define USB_CFG_VENDOR_ID (VENDOR_ID & 0xFF), ((VENDOR_ID >> 8) & 0xFF)
|
||||||
|
/* USB vendor ID for the device, low byte first. If you have registered your
|
||||||
|
* own Vendor ID, define it here. Otherwise you may use one of obdev's free
|
||||||
|
* shared VID/PID pairs. Be sure to read USB-IDs-for-free.txt for rules!
|
||||||
|
* *** IMPORTANT NOTE ***
|
||||||
|
* This template uses obdev's shared VID/PID pair for Vendor Class devices
|
||||||
|
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
|
||||||
|
* the implications!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DEVICE_ID (PRODUCT_ID & 0xFF), ((PRODUCT_ID >> 8) & 0xFF)
|
||||||
|
/* This is the ID of the product, low byte first. It is interpreted in the
|
||||||
|
* scope of the vendor ID. If you have registered your own VID with usb.org
|
||||||
|
* or if you have licensed a PID from somebody else, define it here. Otherwise
|
||||||
|
* you may use one of obdev's free shared VID/PID pairs. See the file
|
||||||
|
* USB-IDs-for-free.txt for details!
|
||||||
|
* *** IMPORTANT NOTE ***
|
||||||
|
* This template uses obdev's shared VID/PID pair for Vendor Class devices
|
||||||
|
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
|
||||||
|
* the implications!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DEVICE_VERSION 0x00, 0x02
|
||||||
|
/* Version number of the device: Minor number first, then major number.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_VENDOR_NAME 'w', 'i', 'n', 'k', 'e', 'y', 'l', 'e', 's', 's', '.', 'k', 'r'
|
||||||
|
#define USB_CFG_VENDOR_NAME_LEN 13
|
||||||
|
/* These two values define the vendor name returned by the USB device. The name
|
||||||
|
* must be given as a list of characters under single quotes. The characters
|
||||||
|
* are interpreted as Unicode (UTF-16) entities.
|
||||||
|
* If you don't want a vendor name string, undefine these macros.
|
||||||
|
* ALWAYS define a vendor name containing your Internet domain name if you use
|
||||||
|
* obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for
|
||||||
|
* details.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DEVICE_NAME 'j', 'j', '4', '0'
|
||||||
|
#define USB_CFG_DEVICE_NAME_LEN 4
|
||||||
|
/* Same as above for the device name. If you don't want a device name, undefine
|
||||||
|
* the macros. See the file USB-IDs-for-free.txt before you assign a name if
|
||||||
|
* you use a shared VID/PID.
|
||||||
|
*/
|
||||||
|
/*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */
|
||||||
|
/*#define USB_CFG_SERIAL_NUMBER_LEN 0 */
|
||||||
|
/* Same as above for the serial number. If you don't want a serial number,
|
||||||
|
* undefine the macros.
|
||||||
|
* It may be useful to provide the serial number through other means than at
|
||||||
|
* compile time. See the section about descriptor properties below for how
|
||||||
|
* to fine tune control over USB descriptors such as the string descriptor
|
||||||
|
* for the serial number.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DEVICE_CLASS 0
|
||||||
|
#define USB_CFG_DEVICE_SUBCLASS 0
|
||||||
|
/* See USB specification if you want to conform to an existing device class.
|
||||||
|
* Class 0xff is "vendor specific".
|
||||||
|
*/
|
||||||
|
#define USB_CFG_INTERFACE_CLASS 3 /* HID */
|
||||||
|
#define USB_CFG_INTERFACE_SUBCLASS 1 /* Boot */
|
||||||
|
#define USB_CFG_INTERFACE_PROTOCOL 1 /* Keyboard */
|
||||||
|
/* See USB specification if you want to conform to an existing device class or
|
||||||
|
* protocol. The following classes must be set at interface level:
|
||||||
|
* HID class is 3, no subclass and protocol required (but may be useful!)
|
||||||
|
* CDC class is 2, use subclass 2 and protocol 1 for ACM
|
||||||
|
*/
|
||||||
|
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 0
|
||||||
|
/* Define this to the length of the HID report descriptor, if you implement
|
||||||
|
* an HID device. Otherwise don't define it or define it to 0.
|
||||||
|
* If you use this define, you must add a PROGMEM character array named
|
||||||
|
* "usbHidReportDescriptor" to your code which contains the report descriptor.
|
||||||
|
* Don't forget to keep the array and this define in sync!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #define USB_PUBLIC static */
|
||||||
|
/* Use the define above if you #include usbdrv.c instead of linking against it.
|
||||||
|
* This technique saves a couple of bytes in flash memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ------------------- Fine Control over USB Descriptors ------------------- */
|
||||||
|
/* If you don't want to use the driver's default USB descriptors, you can
|
||||||
|
* provide our own. These can be provided as (1) fixed length static data in
|
||||||
|
* flash memory, (2) fixed length static data in RAM or (3) dynamically at
|
||||||
|
* runtime in the function usbFunctionDescriptor(). See usbdrv.h for more
|
||||||
|
* information about this function.
|
||||||
|
* Descriptor handling is configured through the descriptor's properties. If
|
||||||
|
* no properties are defined or if they are 0, the default descriptor is used.
|
||||||
|
* Possible properties are:
|
||||||
|
* + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched
|
||||||
|
* at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is
|
||||||
|
* used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if
|
||||||
|
* you want RAM pointers.
|
||||||
|
* + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found
|
||||||
|
* in static memory is in RAM, not in flash memory.
|
||||||
|
* + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash),
|
||||||
|
* the driver must know the descriptor's length. The descriptor itself is
|
||||||
|
* found at the address of a well known identifier (see below).
|
||||||
|
* List of static descriptor names (must be declared PROGMEM if in flash):
|
||||||
|
* char usbDescriptorDevice[];
|
||||||
|
* char usbDescriptorConfiguration[];
|
||||||
|
* char usbDescriptorHidReport[];
|
||||||
|
* char usbDescriptorString0[];
|
||||||
|
* int usbDescriptorStringVendor[];
|
||||||
|
* int usbDescriptorStringDevice[];
|
||||||
|
* int usbDescriptorStringSerialNumber[];
|
||||||
|
* Other descriptors can't be provided statically, they must be provided
|
||||||
|
* dynamically at runtime.
|
||||||
|
*
|
||||||
|
* Descriptor properties are or-ed or added together, e.g.:
|
||||||
|
* #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18))
|
||||||
|
*
|
||||||
|
* The following descriptors are defined:
|
||||||
|
* USB_CFG_DESCR_PROPS_DEVICE
|
||||||
|
* USB_CFG_DESCR_PROPS_CONFIGURATION
|
||||||
|
* USB_CFG_DESCR_PROPS_STRINGS
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_0
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_VENDOR
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_PRODUCT
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
|
||||||
|
* USB_CFG_DESCR_PROPS_HID
|
||||||
|
* USB_CFG_DESCR_PROPS_HID_REPORT
|
||||||
|
* USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver)
|
||||||
|
*
|
||||||
|
* Note about string descriptors: String descriptors are not just strings, they
|
||||||
|
* are Unicode strings prefixed with a 2 byte header. Example:
|
||||||
|
* int serialNumberDescriptor[] = {
|
||||||
|
* USB_STRING_DESCRIPTOR_HEADER(6),
|
||||||
|
* 'S', 'e', 'r', 'i', 'a', 'l'
|
||||||
|
* };
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define USB_CFG_DESCR_PROPS_DEVICE 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_CONFIGURATION USB_PROP_IS_DYNAMIC
|
||||||
|
//#define USB_CFG_DESCR_PROPS_CONFIGURATION 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRINGS 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_0 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_HID USB_PROP_IS_DYNAMIC
|
||||||
|
//#define USB_CFG_DESCR_PROPS_HID 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_HID_REPORT USB_PROP_IS_DYNAMIC
|
||||||
|
//#define USB_CFG_DESCR_PROPS_HID_REPORT 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_UNKNOWN 0
|
||||||
|
|
||||||
|
#define usbMsgPtr_t unsigned short
|
||||||
|
/* If usbMsgPtr_t is not defined, it defaults to 'uchar *'. We define it to
|
||||||
|
* a scalar type here because gcc generates slightly shorter code for scalar
|
||||||
|
* arithmetics than for pointer arithmetics. Remove this define for backward
|
||||||
|
* type compatibility or define it to an 8 bit type if you use data in RAM only
|
||||||
|
* and all RAM is below 256 bytes (tiny memory model in IAR CC).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ----------------------- Optional MCU Description ------------------------ */
|
||||||
|
|
||||||
|
/* The following configurations have working defaults in usbdrv.h. You
|
||||||
|
* usually don't need to set them explicitly. Only if you want to run
|
||||||
|
* the driver on a device which is not yet supported or with a compiler
|
||||||
|
* which is not fully supported (such as IAR C) or if you use a differnt
|
||||||
|
* interrupt than INT0, you may have to define some of these.
|
||||||
|
*/
|
||||||
|
/* #define USB_INTR_CFG MCUCR */
|
||||||
|
/* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */
|
||||||
|
/* #define USB_INTR_CFG_CLR 0 */
|
||||||
|
/* #define USB_INTR_ENABLE GIMSK */
|
||||||
|
/* #define USB_INTR_ENABLE_BIT INT0 */
|
||||||
|
/* #define USB_INTR_PENDING GIFR */
|
||||||
|
/* #define USB_INTR_PENDING_BIT INTF0 */
|
||||||
|
/* #define USB_INTR_VECTOR INT0_vect */
|
||||||
|
|
||||||
|
/* Set INT1 for D- falling edge to count SOF */
|
||||||
|
/* #define USB_INTR_CFG EICRA */
|
||||||
|
#define USB_INTR_CFG_SET ((1 << ISC11) | (0 << ISC10))
|
||||||
|
/* #define USB_INTR_CFG_CLR 0 */
|
||||||
|
/* #define USB_INTR_ENABLE EIMSK */
|
||||||
|
#define USB_INTR_ENABLE_BIT INT1
|
||||||
|
/* #define USB_INTR_PENDING EIFR */
|
||||||
|
#define USB_INTR_PENDING_BIT INTF1
|
||||||
|
#define USB_INTR_VECTOR INT1_vect
|
||||||
|
|
||||||
|
#endif /* __usbconfig_h_included__ */
|
Loading…
Reference in new issue