Help with Teensy2 Layered Keyboard Firmware, Esp the Scanning and Press Sending Parts

Status
Not open for further replies.

fozbstudios

New member
TL;DR
  • Code for scanning of an irregularly shaped matrix
  • Code for sending key presses to a computer
  • Do I need to do anything to prepare for the event of disconnecting the cable(cutting the power) like resetting/saving any variables etc?
  • Is my timer related code implemented correctly/is there a better way to do it?
  • Please suggest any miscellaneous performance improvements/bugfixes you think could be made

Hello and thanks for any help you may be able to provide! To start off with, the key-switches are Cherry MX Blues. Second, the matrices( both the full one and the simplified prototype one in the code) are irregularly shaped. Would this affect any suggested matrix scanning algorithms? Uniquely, the keyboard is built around the concept of layer keys which determine the output of regular keys. Furthermore, modifier and layer keys are sticky. A single tap toggles activity, while a double tap locks it active. Only one layer at a time can be active, but multiple modifiers can be active. Contrastingly, regular keys are not sticky, but will produce output only when held down. I'm not sure how to implement this holding behavior, or if it should go into the press sending or key type related if statements.

On to the code! This code doesn't include my full keymap and is lacking code for detecting physical key presses(matrix scanning) and sending output to a computer. Also, some variables in the structs are unused. I will probably take them out at some point. I'll also attach images of my schematic, PCB, and the full map I eventually plan to have below. The full map may change and is slightly out of date(a layer key is missing).

Code:
int currentLayer=0;
 bool LayerPermDown=false;// for double taps
 uint_16t doubleTapTime=250;
 uint_4t howManyMods=2
 
 typedef struct regKey {
 	uint_2t keyType;//needed because c it doesn't support runtime type checking, one equals regular 2 equals layer and three equals mod
 	uint_4t keyRow; //check if this type is available
 	uint_4t keyCol; //check if availible
 	char layerZeroVal;//always default layer
 	char layerOneVal;
 	char layerTwoVal;
 	bool isPhysDown;
 	//Possibly replace keycol and keyrow with a two-dimensional array
 //containing pointers to each key object in physical keypress
 //function this would be put in parentheses turkeys that don't
 //exist such as when a row/column combination does not have a
 //key there simply use a dummy value or variable that means nothing
 };

 typedef struct layKey {
 	uint_2t keyType;//needed because c it doesn't support runtime type checking, one equals regular 2 equals layer and three equals mod
 	uint_4t keyRow; //check if this type is available
 	uint_4t keyCol; //check if availible
 	int layerNum;
 	elapsedMillis timeElapsed;
 	bool isPhysDown;
	bool isVirtDown;
};

typedef struct modKey {
 	uint_2t keyType;//needed because c it doesn't support runtime type checking, one equals regular 2 equals layer and three equals mod
 	uint_4t modNumber;
	//need to add string for conversion to propper hex val when sending (eg alt, opt, ctl etc.)
 	uint_4t keyRow; //check if this type is available
 	uint_4t keyCol; //check if availible
 	bool isPermDown;
 	elapsedMillis timeElapsed;
 	bool isPhysDown;
	bool isVirtDown;
}

regKey key5 = {1,0,2,"v","a","b",false};
regKey key6 = {1,0,3,"x","c","d",false};
regKey key7 = {1,0,4,"y","e","f",false};
regKey key8 = {1,1,5,"z","g","h",false};
modKey key3={3,1,2,0,0,false,false};
modKey key4={3,0,2,2,0,0,false,false};
layKey key1={2,1,1,1,1,0,false,false};
layKey key2={2,2,1,2,0,false,false};

bool modNormDown[howManyMods]={false};
bool modPermDown[howManyMods]={false};
//PROTOTYPE MAP FOR THIS CODE
//|---------------------|
//|key1key3 key5key6key7|
//|key2key4---------key8|

void cleanup() {
	if(!layerPermDown) {
		currentLayer=0;
	}
	for(i = 0; i < howManyMods; i++)
	{
	 	if(modNormDown[pressedKey.modNum]==true && modPermDown[pressedKey.modNum]==false) {
				modNormDown[pressedKey.modNum]=false;
			
		}
	}

}
//addfunc
if (pressedkey.keyType==1) {
	//send char for active layer
	cleanup();
}
else if (pressedkey.keyType==2) {
	if (currentLayer!=pressedKey.layerNum) {
		//start timer for this key
		layerPermDown=false;
		currentLayer=pressedKey.layerNum;
	}
	else {
		if (pressedKey.elapsedMillis<doubleTapTime) {
			pressedKey.elapsedMillis=0;
			layerPermDown=true;
		}
		else if (layerPermDown==true || pressedKey.elapsedMillis>=doubleTapTime)
			pressedKey.elapsedMillis=0;
			layerPermDown=false;
			currentLayer=0;
			
	}
}

else if (pressedkey.keyType==3) {
	if (modNormDown[pressedKey.modNum]==false && modPermDown[pressedKey.modNum]==false) {
		//start timer for this key
		pressedKey.elapsedMillis=0;
		modNormDown[pressedKey.modNum]=true;
		
	}
	else {
		if (modNormDown[pressedKey.modNum]==true && pressedKey.elapsedMillis<doubleTapTime) {
			pressedKey.elapsedMillis=0;
			modPermDown[pressedKey.modNum]=true;
		}
		else if (layerPermDown==true || pressedKey.elapsedMillis>=doubleTapTime) {
			pressedKey.elapsedMillis=0
			modPermDown[pressedKey.modNum]=false;
			modNormDown[pressedKey.modNum]=false;
		}
	}
}

map:
View attachment 2269

schematic:
View attachment 2271

pcb
View attachment 2270


To recap, I need help with the following:
  • Code for scanning of an irregularly shapped matrix
  • sending keypresses to a computer
  • Do I need to do anything to prepare for the event of disconnecting the cable(cutting the power) like reseting/saving any variables etc
  • Is my timer related code implemented correctly/ is there a better way to do it
  • Please suggest any miscleanious performance improvements/bugfixes you think could be made
 
Last edited:
Status
Not open for further replies.
Back
Top