2011-09-30 05:22:19 +00:00
/* Copyright (C) 2011 by Jacob Alexander
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
// ----- Includes -----
2013-01-26 20:05:28 +00:00
// Compiler Includes
# include <Lib/MacroLib.h>
2011-09-30 05:22:19 +00:00
// Project Includes
2011-10-01 07:54:18 +00:00
# include <led.h>
2011-09-30 05:22:19 +00:00
# include <print.h>
2011-09-30 08:30:34 +00:00
# include <scan_loop.h>
# include <usb_com.h>
2011-09-30 05:22:19 +00:00
// Keymaps
# include <keymap.h>
# include <usb_keys.h>
// Local Includes
# include "macro.h"
2011-10-16 07:45:10 +00:00
// ----- Variables -----
// Keeps track of the sequence used to reflash the teensy in software
static uint8_t Bootloader_ConditionSequence [ ] = { 1 , 16 , 6 , 11 } ;
uint8_t Bootloader_ConditionState = 0 ;
uint8_t Bootloader_NextPositionReady = 1 ;
2011-09-30 05:22:19 +00:00
// ----- Functions -----
2011-10-16 07:45:10 +00:00
void jumpToBootloader ( void )
{
cli ( ) ;
// disable watchdog, if enabled
// disable all peripherals
UDCON = 1 ;
USBCON = ( 1 < < FRZCLK ) ; // disable USB
UCSR1B = 0 ;
_delay_ms ( 5 ) ;
# if defined(__AVR_AT90USB162__) // Teensy 1.0
EIMSK = 0 ; PCICR = 0 ; SPCR = 0 ; ACSR = 0 ; EECR = 0 ;
TIMSK0 = 0 ; TIMSK1 = 0 ; UCSR1B = 0 ;
DDRB = 0 ; DDRC = 0 ; DDRD = 0 ;
PORTB = 0 ; PORTC = 0 ; PORTD = 0 ;
asm volatile ( " jmp 0x3E00 " ) ;
# elif defined(__AVR_ATmega32U4__) // Teensy 2.0
EIMSK = 0 ; PCICR = 0 ; SPCR = 0 ; ACSR = 0 ; EECR = 0 ; ADCSRA = 0 ;
TIMSK0 = 0 ; TIMSK1 = 0 ; TIMSK3 = 0 ; TIMSK4 = 0 ; UCSR1B = 0 ; TWCR = 0 ;
DDRB = 0 ; DDRC = 0 ; DDRD = 0 ; DDRE = 0 ; DDRF = 0 ; TWCR = 0 ;
PORTB = 0 ; PORTC = 0 ; PORTD = 0 ; PORTE = 0 ; PORTF = 0 ;
asm volatile ( " jmp 0x7E00 " ) ;
# elif defined(__AVR_AT90USB646__) // Teensy++ 1.0
EIMSK = 0 ; PCICR = 0 ; SPCR = 0 ; ACSR = 0 ; EECR = 0 ; ADCSRA = 0 ;
TIMSK0 = 0 ; TIMSK1 = 0 ; TIMSK2 = 0 ; TIMSK3 = 0 ; UCSR1B = 0 ; TWCR = 0 ;
DDRA = 0 ; DDRB = 0 ; DDRC = 0 ; DDRD = 0 ; DDRE = 0 ; DDRF = 0 ;
PORTA = 0 ; PORTB = 0 ; PORTC = 0 ; PORTD = 0 ; PORTE = 0 ; PORTF = 0 ;
asm volatile ( " jmp 0xFC00 " ) ;
# elif defined(__AVR_AT90USB1286__) // Teensy++ 2.0
EIMSK = 0 ; PCICR = 0 ; SPCR = 0 ; ACSR = 0 ; EECR = 0 ; ADCSRA = 0 ;
TIMSK0 = 0 ; TIMSK1 = 0 ; TIMSK2 = 0 ; TIMSK3 = 0 ; UCSR1B = 0 ; TWCR = 0 ;
DDRA = 0 ; DDRB = 0 ; DDRC = 0 ; DDRD = 0 ; DDRE = 0 ; DDRF = 0 ;
PORTA = 0 ; PORTB = 0 ; PORTC = 0 ; PORTD = 0 ; PORTE = 0 ; PORTF = 0 ;
asm volatile ( " jmp 0x1FC00 " ) ;
# endif
}
2011-09-30 05:22:19 +00:00
// Given a sampling array, and the current number of detected keypress
// Add as many keypresses from the sampling array to the USB key send array as possible.
2011-10-16 03:01:46 +00:00
inline void keyPressDetection ( uint8_t * keys , uint8_t numberOfKeys , uint8_t * modifiers , uint8_t numberOfModifiers , uint8_t * map )
2011-09-30 05:22:19 +00:00
{
2011-10-16 07:45:10 +00:00
uint8_t Bootloader_KeyDetected = 0 ;
uint8_t processed_keys = 0 ;
2011-10-01 07:54:18 +00:00
2011-10-16 03:01:46 +00:00
// Parse the detection array starting from 1 (all keys are purposefully mapped from 1 -> total as per typical PCB labels)
for ( uint8_t key = 0 ; key < numberOfKeys + 1 ; key + + )
2011-10-01 07:54:18 +00:00
{
2011-10-16 03:01:46 +00:00
if ( keys [ key ] & ( 1 < < 7 ) )
2011-10-01 07:54:18 +00:00
{
2011-10-16 07:45:10 +00:00
processed_keys + + ;
2011-10-16 03:01:46 +00:00
// Display the detected scancode
char tmpStr [ 4 ] ;
int8ToStr ( key , tmpStr ) ;
dPrintStrs ( tmpStr , " " ) ;
2011-09-30 05:22:19 +00:00
2011-10-16 07:45:10 +00:00
// Is this a bootloader sequence key?
if ( ! Bootloader_KeyDetected
& & Bootloader_NextPositionReady
& & key = = Bootloader_ConditionSequence [ Bootloader_ConditionState ] )
{
Bootloader_KeyDetected = 1 ;
Bootloader_NextPositionReady = 0 ;
Bootloader_ConditionState + + ;
}
else if ( Bootloader_ConditionState > 0 & & key = = Bootloader_ConditionSequence [ Bootloader_ConditionState - 1 ] )
{
Bootloader_KeyDetected = 1 ;
}
2011-09-30 05:22:19 +00:00
// Determine if the key is a modifier
2011-10-16 03:01:46 +00:00
uint8_t modFound = 0 ;
2011-09-30 05:22:19 +00:00
for ( uint8_t mod = 0 ; mod < numberOfModifiers ; mod + + ) {
// Modifier found
if ( modifiers [ mod ] = = key ) {
2011-10-16 07:45:10 +00:00
USBKeys_Modifiers | = map [ key ] ;
2011-09-30 05:22:19 +00:00
modFound = 1 ;
break ;
}
}
2011-10-01 07:54:18 +00:00
// Modifier, already done this loop
2011-09-30 05:22:19 +00:00
if ( modFound )
continue ;
// Too many keys
2011-10-01 07:54:18 +00:00
if ( USBKeys_Sent > = USBKeys_MaxSize )
{
info_print ( " USB Key limit reached " ) ;
errorLED ( 1 ) ;
2011-09-30 05:22:19 +00:00
break ;
2011-10-01 07:54:18 +00:00
}
2011-09-30 05:22:19 +00:00
// Allow ignoring keys with 0's
if ( map [ key ] ! = 0 )
2011-10-01 07:54:18 +00:00
USBKeys_Array [ USBKeys_Sent + + ] = map [ key ] ;
2011-09-30 05:22:19 +00:00
}
}
2011-10-16 03:01:46 +00:00
2011-10-16 07:45:10 +00:00
// Boot loader sequence state handler
switch ( processed_keys )
{
// The next bootloader key can now be pressed, if there were no keys processed
case 0 :
Bootloader_NextPositionReady = 1 ;
break ;
// If keys were detected, and it wasn't in the sequence (or there was multiple keys detected), start bootloader sequence over
// This case purposely falls through
case 1 :
if ( Bootloader_KeyDetected )
break ;
default :
Bootloader_ConditionState = 0 ;
break ;
}
2011-10-16 03:01:46 +00:00
// Add debug separator if keys sent via USB
if ( USBKeys_Sent > 0 )
print ( " \033 [1;32m| \033 [0m \n " ) ;
2011-09-30 05:22:19 +00:00
}
2011-10-16 03:01:46 +00:00
inline void process_macros ( void )
2011-09-30 05:22:19 +00:00
{
2011-10-16 07:45:10 +00:00
// Online process macros once (if some were found), until the next USB send
if ( USBKeys_Sent ! = 0 )
return ;
2011-09-30 05:22:19 +00:00
// Debounce Sampling Array to USB Data Array
2011-10-01 07:54:18 +00:00
keyPressDetection ( KeyIndex_Array , KeyIndex_Size , MODIFIER_MASK , sizeof ( MODIFIER_MASK ) , KEYINDEX_MASK ) ;
2011-10-16 07:45:10 +00:00
// Check for bootloader condition
if ( Bootloader_ConditionState = = sizeof ( Bootloader_ConditionSequence ) )
jumpToBootloader ( ) ;
2011-09-30 05:22:19 +00:00
}