Handwired/Dactyl keyboard (#2058)
* Copy the ergodox_ez code to handwired/dactyl
Differences from the Ergodox:
* Use QMK_SUBPROJECT_H instead of QMK_KEYBOARD_H, since it's under
handwired
* Omitted several keymaps. They'll eventually be broken (since the
Dactyl has fewer keys), and I don't want to try to fix them.
* Omitted the keymap images for the default layout, since they depict
a different keyboard.
* Everything that said Ergodox now says Dactyl, naturally.
* [whitespace] Delete trailing whitespace
My editor does this automatically so it's just gonna keep cropping up...
* Cut the dactyl down to the right number of columns
(Remember, throughout matrix.c, everything called "row" is really a
column, and vice-versa).
* Remove LED-related code
* Tighten up the Dactyl's build options
* Whitespace cleanup in twimaster.c
* Hardtabs -> spaces
* No more trailing whitespace
* Typo fix
* Correct the CPU frequency units
The Teensy's CPU definitely doesn't run at 16 petahertz...
* Restore access to ONEHAND_ENABLE
I turned it off in 26d47cb42622d990a7c3335e7fcc151aa3edfbf0 while
desperately debugging; I just wanted to ensure it wasn't causing the
problem I was seeing. It was not, in fact, causing the problem, so it's
back.
Also fixed the swap matrix in dactyl.c, since it still referred to
columns that exist in the Ergodox but not the Dactyl.
* Clearer phrasing about TWI's effect on scan rate
* Fix up the Dactyl's firmware-loading instructions
Sadly, the Dactyl has no hole for the onboard reset button.
* Dvorak keymap for the Dactyl
* The Erincalling Layout
* Erincalling layout: Add a := key
I've been working in Go, which uses := a lot, and it's awkward to type
in this layout.
* Dactyl README: link to the dactyl-keyboard repo
* Add a missing copyright line
I don't know how much this matters? Honestly, it's enough for me that my
name is on the git commit. But hey, let's be consistent until there's a
specific reason not to be, right?
* Dactyl: remove commented-out code
I hate it I hate it I hate it
There's not even any information about what it was trying to do!!!! >:(
* Add a note about the row/column ridiculousness
* [whitespace] realign some constants
* Don't claim B4 is tied to VCC
It doesn't matter at all? I honestly don't know what the reason ever
was. It looks like it dates back to the original ErgoDox and I've never
seen one sentence about the purpose.
I've been skipping that wire for some time, and I promise it works fine.
* Dactyl keymaps: Send RALT for right-hand alt key
Not terribly important but I just like things tidy OK
* typo fix
* Refer to "dactyl.h" explicitly
QMK_SUBPROJECT_H has been working locally, but fails in CI. Strange!
* Dactyl: Don't use QMK_SUBPROJECT_H at all
It's still breaking in CI, even though it was a never a problem locally.
2017-11-26 13:18:59 +06:00
|
|
|
/*************************************************************************
|
|
|
|
* Title: I2C master library using hardware TWI interface
|
|
|
|
* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
|
|
|
|
* File: $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $
|
|
|
|
* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
|
|
|
|
* Target: any AVR device with hardware TWI
|
|
|
|
* Usage: API compatible with I2C Software Library i2cmaster.h
|
|
|
|
**************************************************************************/
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include <compat/twi.h>
|
|
|
|
|
2020-12-16 09:27:23 +06:00
|
|
|
#include "i2cmaster.h"
|
Handwired/Dactyl keyboard (#2058)
* Copy the ergodox_ez code to handwired/dactyl
Differences from the Ergodox:
* Use QMK_SUBPROJECT_H instead of QMK_KEYBOARD_H, since it's under
handwired
* Omitted several keymaps. They'll eventually be broken (since the
Dactyl has fewer keys), and I don't want to try to fix them.
* Omitted the keymap images for the default layout, since they depict
a different keyboard.
* Everything that said Ergodox now says Dactyl, naturally.
* [whitespace] Delete trailing whitespace
My editor does this automatically so it's just gonna keep cropping up...
* Cut the dactyl down to the right number of columns
(Remember, throughout matrix.c, everything called "row" is really a
column, and vice-versa).
* Remove LED-related code
* Tighten up the Dactyl's build options
* Whitespace cleanup in twimaster.c
* Hardtabs -> spaces
* No more trailing whitespace
* Typo fix
* Correct the CPU frequency units
The Teensy's CPU definitely doesn't run at 16 petahertz...
* Restore access to ONEHAND_ENABLE
I turned it off in 26d47cb42622d990a7c3335e7fcc151aa3edfbf0 while
desperately debugging; I just wanted to ensure it wasn't causing the
problem I was seeing. It was not, in fact, causing the problem, so it's
back.
Also fixed the swap matrix in dactyl.c, since it still referred to
columns that exist in the Ergodox but not the Dactyl.
* Clearer phrasing about TWI's effect on scan rate
* Fix up the Dactyl's firmware-loading instructions
Sadly, the Dactyl has no hole for the onboard reset button.
* Dvorak keymap for the Dactyl
* The Erincalling Layout
* Erincalling layout: Add a := key
I've been working in Go, which uses := a lot, and it's awkward to type
in this layout.
* Dactyl README: link to the dactyl-keyboard repo
* Add a missing copyright line
I don't know how much this matters? Honestly, it's enough for me that my
name is on the git commit. But hey, let's be consistent until there's a
specific reason not to be, right?
* Dactyl: remove commented-out code
I hate it I hate it I hate it
There's not even any information about what it was trying to do!!!! >:(
* Add a note about the row/column ridiculousness
* [whitespace] realign some constants
* Don't claim B4 is tied to VCC
It doesn't matter at all? I honestly don't know what the reason ever
was. It looks like it dates back to the original ErgoDox and I've never
seen one sentence about the purpose.
I've been skipping that wire for some time, and I promise it works fine.
* Dactyl keymaps: Send RALT for right-hand alt key
Not terribly important but I just like things tidy OK
* typo fix
* Refer to "dactyl.h" explicitly
QMK_SUBPROJECT_H has been working locally, but fails in CI. Strange!
* Dactyl: Don't use QMK_SUBPROJECT_H at all
It's still breaking in CI, even though it was a never a problem locally.
2017-11-26 13:18:59 +06:00
|
|
|
|
|
|
|
/* define CPU frequency in Hz here if not defined in Makefile */
|
|
|
|
#ifndef F_CPU
|
|
|
|
#define F_CPU 16000000UL
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* I2C clock in Hz */
|
|
|
|
#define SCL_CLOCK 400000L
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
Initialization of the I2C bus interface. Need to be called only once
|
|
|
|
*************************************************************************/
|
|
|
|
void i2c_init(void)
|
|
|
|
{
|
|
|
|
/* initialize TWI clock
|
|
|
|
* minimal values in Bit Rate Register (TWBR) and minimal Prescaler
|
|
|
|
* bits in the TWI Status Register should give us maximal possible
|
|
|
|
* I2C bus speed - about 444 kHz
|
|
|
|
*
|
|
|
|
* for more details, see 20.5.2 in ATmega16/32 secification
|
|
|
|
*/
|
|
|
|
|
|
|
|
TWSR = 0; /* no prescaler */
|
|
|
|
TWBR = 10; /* must be >= 10 for stable operation */
|
|
|
|
|
|
|
|
}/* i2c_init */
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
Issues a start condition and sends address and transfer direction.
|
|
|
|
return 0 = device accessible, 1= failed to access device
|
|
|
|
*************************************************************************/
|
|
|
|
unsigned char i2c_start(unsigned char address)
|
|
|
|
{
|
|
|
|
uint8_t twst;
|
|
|
|
|
|
|
|
// send START condition
|
|
|
|
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
|
|
|
|
|
|
|
|
// wait until transmission completed
|
|
|
|
while(!(TWCR & (1<<TWINT)));
|
|
|
|
|
|
|
|
// check value of TWI Status Register. Mask prescaler bits.
|
|
|
|
twst = TW_STATUS & 0xF8;
|
|
|
|
if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
|
|
|
|
|
|
|
|
// send device address
|
|
|
|
TWDR = address;
|
|
|
|
TWCR = (1<<TWINT) | (1<<TWEN);
|
|
|
|
|
|
|
|
// wail until transmission completed and ACK/NACK has been received
|
|
|
|
while(!(TWCR & (1<<TWINT)));
|
|
|
|
|
|
|
|
// check value of TWI Status Register. Mask prescaler bits.
|
|
|
|
twst = TW_STATUS & 0xF8;
|
|
|
|
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}/* i2c_start */
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
Issues a start condition and sends address and transfer direction.
|
|
|
|
If device is busy, use ack polling to wait until device is ready
|
|
|
|
|
|
|
|
Input: address and transfer direction of I2C device
|
|
|
|
*************************************************************************/
|
|
|
|
void i2c_start_wait(unsigned char address)
|
|
|
|
{
|
|
|
|
uint8_t twst;
|
|
|
|
|
|
|
|
|
|
|
|
while ( 1 )
|
|
|
|
{
|
|
|
|
// send START condition
|
|
|
|
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
|
|
|
|
|
|
|
|
// wait until transmission completed
|
|
|
|
while(!(TWCR & (1<<TWINT)));
|
|
|
|
|
|
|
|
// check value of TWI Status Register. Mask prescaler bits.
|
|
|
|
twst = TW_STATUS & 0xF8;
|
|
|
|
if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
|
|
|
|
|
|
|
|
// send device address
|
|
|
|
TWDR = address;
|
|
|
|
TWCR = (1<<TWINT) | (1<<TWEN);
|
|
|
|
|
|
|
|
// wail until transmission completed
|
|
|
|
while(!(TWCR & (1<<TWINT)));
|
|
|
|
|
|
|
|
// check value of TWI Status Register. Mask prescaler bits.
|
|
|
|
twst = TW_STATUS & 0xF8;
|
|
|
|
if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
|
|
|
|
{
|
|
|
|
/* device busy, send stop condition to terminate write operation */
|
|
|
|
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
|
|
|
|
|
|
|
// wait until stop condition is executed and bus released
|
|
|
|
while(TWCR & (1<<TWSTO));
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
//if( twst != TW_MT_SLA_ACK) return 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}/* i2c_start_wait */
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
Issues a repeated start condition and sends address and transfer direction
|
|
|
|
|
|
|
|
Input: address and transfer direction of I2C device
|
|
|
|
|
|
|
|
Return: 0 device accessible
|
|
|
|
1 failed to access device
|
|
|
|
*************************************************************************/
|
|
|
|
unsigned char i2c_rep_start(unsigned char address)
|
|
|
|
{
|
|
|
|
return i2c_start( address );
|
|
|
|
|
|
|
|
}/* i2c_rep_start */
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
Terminates the data transfer and releases the I2C bus
|
|
|
|
*************************************************************************/
|
|
|
|
void i2c_stop(void)
|
|
|
|
{
|
|
|
|
/* send stop condition */
|
|
|
|
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
|
|
|
|
|
|
|
// wait until stop condition is executed and bus released
|
|
|
|
while(TWCR & (1<<TWSTO));
|
|
|
|
|
|
|
|
}/* i2c_stop */
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
Send one byte to I2C device
|
|
|
|
|
|
|
|
Input: byte to be transfered
|
|
|
|
Return: 0 write successful
|
|
|
|
1 write failed
|
|
|
|
*************************************************************************/
|
|
|
|
unsigned char i2c_write( unsigned char data )
|
|
|
|
{
|
|
|
|
uint8_t twst;
|
|
|
|
|
|
|
|
// send data to the previously addressed device
|
|
|
|
TWDR = data;
|
|
|
|
TWCR = (1<<TWINT) | (1<<TWEN);
|
|
|
|
|
|
|
|
// wait until transmission completed
|
|
|
|
while(!(TWCR & (1<<TWINT)));
|
|
|
|
|
|
|
|
// check value of TWI Status Register. Mask prescaler bits
|
|
|
|
twst = TW_STATUS & 0xF8;
|
|
|
|
if( twst != TW_MT_DATA_ACK) return 1;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}/* i2c_write */
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
Read one byte from the I2C device, request more data from device
|
|
|
|
|
|
|
|
Return: byte read from I2C device
|
|
|
|
*************************************************************************/
|
|
|
|
unsigned char i2c_readAck(void)
|
|
|
|
{
|
|
|
|
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
|
|
|
|
while(!(TWCR & (1<<TWINT)));
|
|
|
|
|
|
|
|
return TWDR;
|
|
|
|
|
|
|
|
}/* i2c_readAck */
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
Read one byte from the I2C device, read is followed by a stop condition
|
|
|
|
|
|
|
|
Return: byte read from I2C device
|
|
|
|
*************************************************************************/
|
|
|
|
unsigned char i2c_readNak(void)
|
|
|
|
{
|
|
|
|
TWCR = (1<<TWINT) | (1<<TWEN);
|
|
|
|
while(!(TWCR & (1<<TWINT)));
|
|
|
|
|
|
|
|
return TWDR;
|
|
|
|
|
|
|
|
}/* i2c_readNak */
|