aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2021-05-04 02:22:31 +0200
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2021-05-04 02:22:31 +0200
commitf29443cd40f9050beedab3a822b6e0f24fb789cd (patch)
tree5f53eb3d8c904af00f13d58976c8d6f04ba6339e
parentaf302afcb0aaa08bd9c093b2c8ff20647a001919 (diff)
downloadtmk7637-f29443cd40f9050beedab3a822b6e0f24fb789cd.tar.gz
optimized the LED and buzzer wiring
* since we use timer 3 exclusively for the buzzer but trigger the pin using an IRQ handler, there is no longer any need to occupy a high-resolution pin for the buzzer. * PD5 became a new high resolution LED * PD0 became the new buzzer pin * rearranged the pins used for the different LEDs so that the distribution of high-resolution LEDs is symmetric * Timer 0 is no longer used/modified by setting LEDs. This avoids some workarounds as timer 0 is also used by tmk's timer module. * The song routines could be slightly improved using the timer module. * documented the LED and buzzer pinout in README
-rw-r--r--README.md14
-rw-r--r--command.c2
-rw-r--r--led.c23
-rw-r--r--matrix.c4
-rw-r--r--pwm.c59
-rw-r--r--pwm.h3
-rw-r--r--song.c51
7 files changed, 52 insertions, 104 deletions
diff --git a/README.md b/README.md
index 36f36ca..0516060 100644
--- a/README.md
+++ b/README.md
@@ -113,11 +113,21 @@ Now, solder wires *on the backside* of the PCBs to the following pins of the for
![8212](docs/8212.jpg)
-These wires connect to the Teensy in the following order: __FIXME__
+These wires connect to the Teensy in the following order:
+
+8212 Pin | Teensy Pin
+-------- | ----------
+4 | PB5
+6 | PD1
+8 | PB7
+10 | PB4
+15 | PB6
+17 | PD2
+21 | PD3
Desolder the buzzer's 390R resistor and connect the side *facing away* from it
to a jumper cable.
-It will connect to pin __FIXME__ of the Teensy.
+It will connect to pin PD0 of the Teensy.
Desolder the IFFS cable.
diff --git a/command.c b/command.c
index 6827706..cb0c270 100644
--- a/command.c
+++ b/command.c
@@ -38,7 +38,7 @@ bool command_extra(uint8_t code)
dprintf("new keyclick mode: %u\n", keyclick_mode);
/* FIXME: Perhaps do this in matrix_scan() */
keyclick_solenoid_set(false);
- pwm_pb5_set_tone(0);
+ pwm_pd0_set_tone(0);
/* update the keyclick mode LED */
led_set(host_keyboard_leds());
return true;
diff --git a/led.c b/led.c
index c7e5933..0d92563 100644
--- a/led.c
+++ b/led.c
@@ -40,33 +40,28 @@ void led_set(uint8_t usb_led)
else
PORTD |= (1 << PD3);
- /*
- * 1st LED on first row (G00).
- *
- * NOTE: This will automatically disable PWM mode, so it will not
- * interfere with timer 0 and tmk's timer module.
- */
- pwm_pd0_set_led(usb_led & (1 << USB_LED_NUM_LOCK) ? 255 : 0);
+ /* 1st LED on first row (G00). */
+ pwm_pb5_set_led(usb_led & (1 << USB_LED_NUM_LOCK) ? 255 : 0);
/* 2nd LED on first row (G01): Highlight keyclick mode. */
- pwm_pb7_set_led(keyclick_mode*255/(KEYCLICK_MAX-1));
+ pwm_pd1_set_led(keyclick_mode*255/(KEYCLICK_MAX-1));
/* 3rd LED on the first row (G02) */
- pwm_pd1_set_led(usb_led & (1 << USB_LED_COMPOSE) ? 255 : 0);
+ pwm_pb7_set_led(usb_led & (1 << USB_LED_COMPOSE) ? 255 : 0);
/*
* 4th LED (G03) are currently not triggerable via USB.
* Could be triggered as the "backlight".
*/
- pwm_pb6_set_led(0);
+ pwm_pb4_set_led(0);
/* 5th LED on the first row (G04) */
- pwm_pb4_set_led(usb_led & (1 << USB_LED_SCROLL_LOCK) ? 255 : 0);
+ pwm_pb6_set_led(usb_led & (1 << USB_LED_SCROLL_LOCK) ? 255 : 0);
/*
* 6th LED on the first row (G53).
*
- * Triggering this LED (PD2) will also enable the buzzer (PB5),
+ * Triggering this LED (PD2) will also enable the buzzer (PD0),
* so we have got a way to beep from userspace (see ./k7637-beep.sh).
*
* The original firmware also had the error display on G53
@@ -74,9 +69,9 @@ void led_set(uint8_t usb_led)
*/
if (usb_led & (1 << USB_LED_KANA)) {
PORTD &= ~(1 << PD2);
- pwm_pb5_set_tone(2200);
+ pwm_pd0_set_tone(2200);
} else {
PORTD |= (1 << PD2);
- pwm_pb5_set_tone(0);
+ pwm_pd0_set_tone(0);
}
}
diff --git a/matrix.c b/matrix.c
index 5c4ecbd..cbb011d 100644
--- a/matrix.c
+++ b/matrix.c
@@ -143,7 +143,7 @@ uint8_t matrix_scan(void)
case KEYCLICK_BUZZER:
if (matrix_debouncing_pressed_keys > matrix_pressed_keys) {
- pwm_pb5_set_tone(550);
+ pwm_pd0_set_tone(550);
keyclick_time = timer_read();
}
break;
@@ -229,7 +229,7 @@ uint8_t matrix_scan(void)
case KEYCLICK_BUZZER:
if (!(host_keyboard_leds() & (1 << USB_LED_KANA)))
- pwm_pb5_set_tone(0);
+ pwm_pd0_set_tone(0);
break;
default:
diff --git a/pwm.c b/pwm.c
index 97c3dac..82fd106 100644
--- a/pwm.c
+++ b/pwm.c
@@ -97,47 +97,6 @@ static const uint16_t pwm_table16[256] PROGMEM = {
};
/**
- * Configure a PWM pin of Timer 0 (8-bit resolution).
- *
- * @note Timer 0 is used by tmk's timer module as well.
- * You can therefore only temporarilly PWM-modulate using timer 0
- * (ie. NOT during matrix scanning), cannot use any timer module functions
- * and should call timer_init() afterwards.
- * This can be easily resolved by using pwm_pb5_set_led() for one of the LEDs
- * and redistribute all the LED.
- * The buzzer can then use the no longer used PD0 since it's manually
- * IRQ-triggered anyway.
- *
- * @param channel Channel to initialize.
- * 0 (OC0A/PB7), 1 (OC0B/PD0)
- */
-static void pwm_timer0_init(uint8_t channel)
-{
- /* Fast PWM on OC0x, inverted duty cycle, TOP = 0xFF */
- TCCR0A |= (0b11 << (3-channel)*2) | 0b11;
- /* no prescaling */
- TCCR0B = 0b00000001;
-}
-
-void pwm_pd0_set_led(uint8_t brightness)
-{
- switch (brightness) {
- case 0:
- TCCR0A &= ~0b00110000;
- PORTD |= (1 << PD0);
- break;
- case 255:
- TCCR0A &= ~0b00110000;
- PORTD &= ~(1 << PD0);
- break;
- default:
- pwm_timer0_init(1);
- OCR0B = pgm_read_byte(&pwm_table8[brightness]);
- break;
- }
-}
-
-/**
* Configure a PWM pin of Timer 1 (16-bit resolution).
*
* @param channel Channel to initialize.
@@ -262,24 +221,22 @@ void pwm_pd1_set_led(uint8_t brightness)
/**
* Set a LED by position in the first row.
*
- * @bug The pins used should be rescrambled after we freed PD0.
- *
* @param led LED to set (0-4).
* @param brightness Brightness level to set.
*/
void pwm_set_led(uint8_t led, uint8_t brightness)
{
switch (led) {
- case 0: pwm_pd0_set_led(brightness); break;
- case 1: pwm_pb7_set_led(brightness); break;
- case 2: pwm_pd1_set_led(brightness); break;
- case 3: pwm_pb6_set_led(brightness); break;
- case 4: pwm_pb4_set_led(brightness); break;
+ case 0: pwm_pb5_set_led(brightness); break;
+ case 1: pwm_pd1_set_led(brightness); break;
+ case 2: pwm_pb7_set_led(brightness); break;
+ case 3: pwm_pb4_set_led(brightness); break;
+ case 4: pwm_pb6_set_led(brightness); break;
}
}
/**
- * Play a tone on PB5 (the buzzer).
+ * Play a tone on PD0 (the buzzer).
*
* @note This uses timer 3 with an IRQ, even though we cannot
* use one of the Timer 3 PWM pins -- they are required for matrix
@@ -305,7 +262,7 @@ void pwm_set_led(uint8_t led, uint8_t brightness)
*
* @param freq Frequency to play. If 0, disables the buzzer.
*/
-void pwm_pb5_set_tone(uint16_t freq)
+void pwm_pd0_set_tone(uint16_t freq)
{
if (!freq) {
/*
@@ -343,5 +300,5 @@ void pwm_pb5_set_tone(uint16_t freq)
ISR(TIMER3_COMPA_vect, ISR_NOBLOCK)
{
- PORTB ^= (1 << PB5);
+ PORTD ^= (1 << PD0);
}
diff --git a/pwm.h b/pwm.h
index f1e0d3f..4a68f4b 100644
--- a/pwm.h
+++ b/pwm.h
@@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h>
-void pwm_pd0_set_led(uint8_t brightness);
void pwm_pd1_set_led(uint8_t brightness);
void pwm_pb4_set_led(uint8_t brightness);
void pwm_pb5_set_led(uint8_t brightness);
@@ -29,6 +28,6 @@ void pwm_pb7_set_led(uint8_t brightness);
void pwm_set_led(uint8_t led, uint8_t brightness);
-void pwm_pb5_set_tone(uint16_t freq);
+void pwm_pd0_set_tone(uint16_t freq);
#endif
diff --git a/song.c b/song.c
index 4abbb03..d58ff16 100644
--- a/song.c
+++ b/song.c
@@ -193,11 +193,13 @@ void song_play_ruinen(void)
{
/* could be activated due to keyclick mode */
keyclick_solenoid_set(false);
- pwm_pb5_set_tone(0);
+ pwm_pd0_set_tone(0);
uint8_t i = 0;
for (long unsigned int cur_note = 0; cur_note < sizeof(song_ruinen)/sizeof(song_ruinen[0]); cur_note++) {
- pwm_pb5_set_tone(pgm_read_word(&song_ruinen[cur_note].freq));
+ uint16_t cur_note_time = timer_read();
+
+ pwm_pd0_set_tone(pgm_read_word(&song_ruinen[cur_note].freq));
uint8_t max_brightness = ((uint32_t)pgm_read_word(&song_ruinen[cur_note].freq)*255)/600;
uint16_t fade_dur = pgm_read_word(&song_ruinen[cur_note].dur)/2/(max_brightness+1);
@@ -206,14 +208,6 @@ void song_play_ruinen(void)
delay_long(fade_dur);
}
- /*
- * The fade duration is probably not very precise, so compensate for it.
- *
- * FIXME: Once timer 0 is freed, we should use timer_read() and timer_elapsed()
- * which will be more precise.
- */
- delay_long(pgm_read_word(&song_ruinen[cur_note].dur) - fade_dur*(max_brightness+1)*2);
-
for (int16_t brightness = max_brightness; brightness >= 0; brightness--) {
pwm_set_led(i % 5, brightness);
delay_long(fade_dur);
@@ -221,12 +215,14 @@ void song_play_ruinen(void)
if (pgm_read_word(&song_ruinen[cur_note].freq))
i++;
- }
- pwm_pb5_set_tone(0);
+ /* The fade duration is probably not very precise, so compensate for it. */
+ uint16_t elapsed = timer_elapsed(cur_note_time);
+ if (elapsed < pgm_read_word(&song_ruinen[cur_note].dur))
+ delay_long(pgm_read_word(&song_ruinen[cur_note].dur) - elapsed);
+ }
- /* we screwed up timer 0 settings and they are also used by the timer module */
- timer_init();
+ pwm_pd0_set_tone(0);
/* restore the previous lock lights */
led_set(host_keyboard_leds());
@@ -414,7 +410,7 @@ void song_play_kitt(void)
{
/* could be activated due to keyclick mode */
keyclick_solenoid_set(false);
- pwm_pb5_set_tone(0);
+ pwm_pd0_set_tone(0);
int16_t i;
@@ -423,38 +419,29 @@ void song_play_kitt(void)
song_larsen_light(i);
long unsigned int cur_note = 0;
- uint16_t cur_note_dur = 0;
+ uint16_t cur_note_time = timer_read();
int8_t dir = 1;
for (i = 0; cur_note < sizeof(song_knight_rider)/sizeof(song_knight_rider[0]); i += dir) {
- /*
- * FIXME: Once we freed up timer 0 by rearranging the LED pins,
- * it might be more precise to use timer_read()/timer_elapsed() to wait for the next note.
- */
- if (cur_note_dur < LARSEN_CURVE_STEP) {
- cur_note_dur = pgm_read_word(&song_knight_rider[cur_note].dur);
- pwm_pb5_set_tone(pgm_read_word(&song_knight_rider[cur_note].freq));
- }
+ pwm_pd0_set_tone(pgm_read_word(&song_knight_rider[cur_note].freq));
song_larsen_light(i);
- cur_note_dur -= LARSEN_CURVE_STEP;
- if (cur_note_dur < LARSEN_CURVE_STEP)
- cur_note++;
-
if (i == sizeof(song_larsen_curve)-1 || (dir < 0 && i == 0))
dir *= -1;
+
+ if (timer_elapsed(cur_note_time) >= pgm_read_word(&song_knight_rider[cur_note].dur)) {
+ cur_note_time = timer_read();
+ cur_note++;
+ }
}
- pwm_pb5_set_tone(0);
+ pwm_pd0_set_tone(0);
/* fade out larsen light */
while (i < sizeof(song_larsen_curve)*3/2)
song_larsen_light(i++);
- /* we screwed up timer 0 settings and they are also used by the timer module */
- timer_init();
-
/* restore the previous lock lights */
led_set(host_keyboard_leds());
}