浏览代码

replace rowEnd with KEY_COUNT, remove read_pins_mask_t, print_free_RAM()

tags/v0.5.0
wolfv6 8 年前
父节点
当前提交
a725a74831

+ 45
- 36
examples/keybrd_shift_register/keybrd_shift_register.ino 查看文件

with every 4th input pin connected to a pull-down resistor and matrix column, also the 31st key. with every 4th input pin connected to a pull-down resistor and matrix column, also the 31st key.
Unused input pins are not grounded, so add this line to RowScanner_SPIShiftRegisters::scan(): Unused input pins are not grounded, so add this line to RowScanner_SPIShiftRegisters::scan():
//clear unpowered pins (for testing on breadboard) //clear unpowered pins (for testing on breadboard)
rowState &= 0b01010001000100010001000100010001;
rowState &= 0b11110001000100010001000100010001; //todo


Layout Layout
| Left |**0**|**1**| | Right |**0**|**1**|**2**|**3**|**4**|**5**|**6**|**7**|**8**|
|:-----:|-----|-----| |:-----:|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| **0** | a | b | | **0** | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| **1** | c | d | | **1** | a | b | c | d | e | f | g | h | i |
| Left | **0**|**1**| | Right |**0**|**1**|**2**|**3**|**4**|**5**|**6**|**7**|**8**|
|:-----:|------|-----| |:-----:|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| **0** |capLck| a | | **0** | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| **1** | b | c | | **1** | a | b | c | d | e | f | g | h | i |
*/ */
// ################## GLOBAL ################### // ################## GLOBAL ###################
// ================= INCLUDES ================== // ================= INCLUDES ==================
#include <Debug.h> #include <Debug.h>
#include <ScanDelay.h> #include <ScanDelay.h>
#include <LED_PinNumber.h>


//Codes //Codes
#include <Code_Sc.h> #include <Code_Sc.h>
#include <Code_LEDLock.h>


//Matrix //Matrix
#include <Row_uC.h> #include <Row_uC.h>


// ================= LEFT PINS ================= // ================= LEFT PINS =================
uint8_t readPins[] = {14, 15}; uint8_t readPins[] = {14, 15};
uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins);
uint8_t KEY_COUNT = sizeof(readPins)/sizeof(*readPins);


// ==================== LEDs ===================
LED_PinNumber LED1(16);

//sometimes OS takes 6 seconds to recongnize keyboard, LED blinks from the begining
void wait()
{
for (uint8_t count = 0; count < 6; count++)
{
//print count
Keyboard.print(count);
Keyboard.print(F(" "));

//blink LED
LED1.on();
delay(500);
LED1.off();
delay(500);
}
}
// =================== CODES =================== // =================== CODES ===================
Code_Sc s_a(KEY_A); Code_Sc s_a(KEY_A);
Code_Sc s_b(KEY_B); Code_Sc s_b(KEY_B);
Code_Sc s_h(KEY_H); Code_Sc s_h(KEY_H);
Code_Sc s_i(KEY_I); Code_Sc s_i(KEY_I);


Code_Sc s_u(KEY_U);
Code_Sc s_v(KEY_V);
Code_Sc s_w(KEY_W);
Code_Sc s_x(KEY_X);

Code_Sc s_z(KEY_Z);

Code_Sc s_0(KEY_0); Code_Sc s_0(KEY_0);
Code_Sc s_1(KEY_1); Code_Sc s_1(KEY_1);
Code_Sc s_2(KEY_2); Code_Sc s_2(KEY_2);
Code_Sc s_6(KEY_6); Code_Sc s_6(KEY_6);
Code_Sc s_7(KEY_7); Code_Sc s_7(KEY_7);
Code_Sc s_8(KEY_8); Code_Sc s_8(KEY_8);
Code_Sc s_z(KEY_Z);

Code_LEDLock o_capsLock(KEY_CAPS_LOCK, LED1);


// ================= LEFT ROWS ================= // ================= LEFT ROWS =================
Key* ptrsKeys_L0[] = { &s_a, &s_b };
Row_uC row_L0(0, readPins, READ_PIN_COUNT, ptrsKeys_L0);
Key* ptrsKeys_L0[] = { &o_capsLock, &s_a };
Row_uC row_L0(0, readPins, ptrsKeys_L0, KEY_COUNT);


Key* ptrsKeys_L1[] = { &s_c, &s_d };
Row_uC row_L1(1, readPins, READ_PIN_COUNT, ptrsKeys_L1);
Key* ptrsKeys_L1[] = { &s_b, &s_c };
Row_uC row_L1(1, readPins, ptrsKeys_L1, KEY_COUNT);


// ================= RIGHT ROWS ================ // ================= RIGHT ROWS ================
//typedef should be large in /home/wolfv/Documents/Arduino/keybrd_proj/keybrd/src/config_keybrd.h //typedef should be large in /home/wolfv/Documents/Arduino/keybrd_proj/keybrd/src/config_keybrd.h
Row_ShiftRegisters row_R0(8, ptrsKeys_R0, KEY_R0_COUNT); Row_ShiftRegisters row_R0(8, ptrsKeys_R0, KEY_R0_COUNT);
*/ */


//prints 0 1 2 3 4 5 6 7 8, microseconds_per_scan=87 with SAMPLE_COUNT 4
//prints 0 1 2 3 3 4 5 6, microseconds_per_scan=87 with SAMPLE_COUNT 4
Key* ptrsKeys_R0[] = { &s_0, &s_z, &s_z, &s_z, &s_1, &s_z, &s_z, &s_z, Key* ptrsKeys_R0[] = { &s_0, &s_z, &s_z, &s_z, &s_1, &s_z, &s_z, &s_z,
&s_2, &s_z, &s_z, &s_z, &s_3, &s_z, &s_z, &s_z, &s_2, &s_z, &s_z, &s_z, &s_3, &s_z, &s_z, &s_z,
&s_4, &s_z, &s_z, &s_z, &s_5, &s_z, &s_z, &s_z, &s_4, &s_z, &s_z, &s_z, &s_5, &s_z, &s_z, &s_z,
&s_6, &s_z, &s_z, &s_z, &s_7, &s_z, &s_8 }; //31-key limit because endRow
&s_6, &s_z, &s_z, &s_z, &s_3, &s_4, &s_5, &s_6 };
const uint8_t KEY_R0_COUNT = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); const uint8_t KEY_R0_COUNT = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0);
Row_ShiftRegisters row_R0(8, ptrsKeys_R0, KEY_R0_COUNT); Row_ShiftRegisters row_R0(8, ptrsKeys_R0, KEY_R0_COUNT);


//prints a b c d e f g h i
//prints a b c d u v w x
Key* ptrsKeys_R1[] = { &s_a, &s_z, &s_z, &s_z, &s_b, &s_z, &s_z, &s_z, Key* ptrsKeys_R1[] = { &s_a, &s_z, &s_z, &s_z, &s_b, &s_z, &s_z, &s_z,
&s_c, &s_z, &s_z, &s_z, &s_d, &s_z, &s_z, &s_z, &s_c, &s_z, &s_z, &s_z, &s_d, &s_z, &s_z, &s_z,
&s_e, &s_z, &s_z, &s_z, &s_f, &s_z, &s_z, &s_z, &s_e, &s_z, &s_z, &s_z, &s_f, &s_z, &s_z, &s_z,
&s_g, &s_z, &s_z, &s_z, &s_h, &s_z, &s_i }; //31-key limit because endRow
&s_g, &s_z, &s_z, &s_z, &s_u, &s_v, &s_w, &s_x };
const uint8_t KEY_R1_COUNT = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1); const uint8_t KEY_R1_COUNT = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1);
Row_ShiftRegisters row_R1(9, ptrsKeys_R1, KEY_R1_COUNT); Row_ShiftRegisters row_R1(9, ptrsKeys_R1, KEY_R1_COUNT);


const uint8_t LED_PIN = 16; //indicates wait

//sometimes OS takes 6 seconds to recongnize keyboard, LED blinks from the begining
void wait()
{
for (uint8_t count = 0; count < 6; count++)
{
//print count
Keyboard.print(count);
Keyboard.print(F(" "));

//blink LED
digitalWrite(LED_PIN, HIGH);
delay(900);
digitalWrite(LED_PIN, LOW);
delay(100);
}
}
// ################### MAIN #################### // ################### MAIN ####################
void setup() void setup()
{ {
pinMode (LED_PIN, OUTPUT);
Keyboard.begin(); Keyboard.begin();


wait(); wait();
row_R0.begin(); row_R0.begin();
row_R1.begin(); row_R1.begin();


Keyboard.print(F("keybrd_shift_reg.ino "));
debug.print_free_RAM();
Keyboard.println(F("keybrd_shift_reg.ino"));
} }


void loop() void loop()

+ 1
- 1
src/Code_LEDLock.cpp 查看文件

*/ */
if (keyboard_leds & USB_LED_bit) //if USB_LED_bit is set if (keyboard_leds & USB_LED_bit) //if USB_LED_bit is set
{ {
refLED.off(); //LED on-off seem inverted, but it works for active high
refLED.off(); //LED on-off seem inverted, but it works for active low and active high
} }
else else
{ {

+ 1
- 2
src/ColPort_PCA9655E.cpp 查看文件

/* /*
configures column port's configuration, input, and pins. configures column port's configuration, input, and pins.
*/ */
ColPort_PCA9655E::ColPort_PCA9655E
(IOExpanderPort& port, const uint8_t colPins)
ColPort_PCA9655E::ColPort_PCA9655E (IOExpanderPort& port, const uint8_t colPins)
: ColPort(colPins), port(port), configurationByteCommand(port.num + 6), inputByteCommand(port.num) : ColPort(colPins), port(port), configurationByteCommand(port.num + 6), inputByteCommand(port.num)
{} {}

+ 0
- 8
src/Debug.cpp 查看文件

#include "Debug.h" #include "Debug.h"
#include "getFreeSRAM.h"
void Debug::print_free_RAM()
{
delay(1000); //give OS time to find USB
Keyboard.print(F("Free SRAM = "));
Keyboard.println( getFreeSRAM() );
}
void Debug::print_microseconds_per_scan() void Debug::print_microseconds_per_scan()
{ {

+ 0
- 1
src/Debug.h 查看文件

unsigned int scanCount = 0; unsigned int scanCount = 0;
public: public:
void print_free_RAM(); //print free SRAM, call this from setup()
void print_microseconds_per_scan(); //print microseconds per scan every second void print_microseconds_per_scan(); //print microseconds per scan every second
void print_scans_per_second(); //print scans per second every second void print_scans_per_second(); //print scans per second every second
}; };

+ 1
- 2
src/RowBase.cpp 查看文件

/* /*
pressRelease() calls key's press() or release() function if it was pressed or released. pressRelease() calls key's press() or release() function if it was pressed or released.
Both parameters are bitwise. Both parameters are bitwise.
rowEnd bit marks positioned immediatly after last key of row.
*/ */
void RowBase::pressRelease(const uint8_t KEY_COUNT, const read_pins_t debouncedChanged) void RowBase::pressRelease(const uint8_t KEY_COUNT, const read_pins_t debouncedChanged)
{ {
read_pins_t isFallingEdge; //bitwise, 1 means falling edge read_pins_t isFallingEdge; //bitwise, 1 means falling edge
read_pins_t isRisingEdge; //bitwise, 1 means rising edge read_pins_t isRisingEdge; //bitwise, 1 means rising edge
read_pins_mask_t rowMask; //bitwise, active col bit is 1
read_pins_t rowMask; //bitwise, active col bit is 1
uint8_t col; //index for ptrsKeys[col] array uint8_t col; //index for ptrsKeys[col] array
//bit=1 if last debounced changed from 1 to 0, else bit=0 //bit=1 if last debounced changed from 1 to 0, else bit=0

+ 1
- 1
src/RowBase.h 查看文件

virtual void keyWasPressed(); virtual void keyWasPressed();
protected: protected:
read_pins_t debounced; //bitwise, 1 means pressed, 0 means released read_pins_t debounced; //bitwise, 1 means pressed, 0 means released
void pressRelease(const read_pins_mask_t rowEnd, const read_pins_t debouncedChanged);
void pressRelease(const uint8_t KEY_COUNT, const read_pins_t debouncedChanged);
public: public:
RowBase(Key *const ptrsKeys[]) : ptrsKeys(ptrsKeys), debounced(0) { } RowBase(Key *const ptrsKeys[]) : ptrsKeys(ptrsKeys), debounced(0) { }
virtual void process()=0; virtual void process()=0;

+ 7
- 9
src/RowScanner_PinsArray.cpp 查看文件

} }


/* scan() Strobes the row and reads the columns. /* scan() Strobes the row and reads the columns.
Sets rowEnd and returns rowState.
rowEnd is a bitwise row mask, one col per bit, where active col bit is 1.
At end of function, 1 bit marks place immediatly after last key of row.
rowEnd is a larger type than portMask so that it can not overflow.
Sets KEY_COUNT and returns rowState.


https://www.arduino.cc/en/Tutorial/DigitalPins https://www.arduino.cc/en/Tutorial/DigitalPins
https://www.arduino.cc/en/Reference/PinMode https://www.arduino.cc/en/Reference/PinMode
https://www.arduino.cc/en/Reference/DigitalRead https://www.arduino.cc/en/Reference/DigitalRead
https://www.arduino.cc/en/Reference/Constants > Digital Pins modes: INPUT, INPUT_PULLUP, and OUTPUT https://www.arduino.cc/en/Reference/Constants > Digital Pins modes: INPUT, INPUT_PULLUP, and OUTPUT
*/ */
read_pins_t RowScanner_PinsArray::scan(read_pins_mask_t& rowEnd)
read_pins_t RowScanner_PinsArray::scan(uint8_t& keyCount)
{ {
read_pins_t rowState = 0; //bitwise
rowEnd = 1;
read_pins_t rowState = 0; //bitwise, one col per bit, 1 means key is pressed
read_pins_t rowMask = 1; //bitwise, one col per bit, active col bit is 1


//strobe row on //strobe row on
if (ACTIVE_HIGH) if (ACTIVE_HIGH)
{ {
if ( digitalRead(READ_PINS[i]) == ACTIVE_HIGH ) if ( digitalRead(READ_PINS[i]) == ACTIVE_HIGH )
{ {
rowState |= rowEnd;
rowState |= rowMask;
} }
rowEnd <<= 1;
rowMask <<= 1;
} }


//strobe row off //strobe row off
digitalWrite(STROBE_PIN, HIGH); digitalWrite(STROBE_PIN, HIGH);
} }


keyCount = READ_PIN_COUNT;
return rowState; return rowState;
} }

+ 2
- 4
src/RowScanner_PinsArray.h 查看文件

#include <ColPort.h> #include <ColPort.h>


/* RowScanner_PinsArray class uses Arduino pin numbers (not port pin numbers). /* RowScanner_PinsArray class uses Arduino pin numbers (not port pin numbers).
The maximum keys per row is 31, because Arduino's largest type is 32 bits and rowEnd consumes the last bit.
Constructor is in RowScanner_PinsArray.cpp Constructor is in RowScanner_PinsArray.cpp
*/ */
class RowScanner_PinsArray class RowScanner_PinsArray
const uint8_t READ_PIN_COUNT; //number of read pins const uint8_t READ_PIN_COUNT; //number of read pins
public: public:
RowScanner_PinsArray(const uint8_t STROBE_PIN, RowScanner_PinsArray(const uint8_t STROBE_PIN,
const uint8_t READ_PINS[], const uint8_t READ_PIN_COUNT);
virtual read_pins_t scan(read_pins_mask_t& rowEnd);
//read_pins_t getRowState(read_pins_mask_t& rowEnd);
const uint8_t READ_PINS[], const uint8_t READ_PIN_COUNT); //todo rename READ_PIN_COUNT to KEY_COUNT ??
virtual read_pins_t scan(uint8_t& KEY_COUNT);
}; };
#endif #endif



+ 0
- 2
src/RowScanner_PinsBitwise.cpp 查看文件

#include "RowScanner_PinsBitwise.h" #include "RowScanner_PinsBitwise.h"
/* /*
Strobes the row and reads the columns. Strobes the row and reads the columns.
Sets rowEnd and returns rowState.
*/ */
ColPort* const RowScanner_PinsBitwise::scan() ColPort* const RowScanner_PinsBitwise::scan()
{ {
refRowPort.setActivePinHigh(strobePin); refRowPort.setActivePinHigh(strobePin);
} }
// return getRowState(refColPort, rowEnd);
return &refColPort; return &refColPort;
} }

+ 6
- 6
src/RowScanner_SPIShiftRegisters.cpp 查看文件



//constructor //constructor
RowScanner_SPIShiftRegisters::RowScanner_SPIShiftRegisters(const uint8_t STROBE_PIN, uint8_t KEY_COUNT) RowScanner_SPIShiftRegisters::RowScanner_SPIShiftRegisters(const uint8_t STROBE_PIN, uint8_t KEY_COUNT)
: STROBE_PIN(STROBE_PIN), ROW_END(1 << KEY_COUNT), BYTE_COUNT(ceil (float(KEY_COUNT)/8))
: STROBE_PIN(STROBE_PIN), BYTE_COUNT(ceil (float(KEY_COUNT)/8)), KEY_COUNT(KEY_COUNT)
{ {
//configure controller to communicate with shift register matrix //configure controller to communicate with shift register matrix
pinMode(STROBE_PIN, OUTPUT); pinMode(STROBE_PIN, OUTPUT);
} }


/* /*
Sets rowEnd and returns rowState.
Sets keyCount and returns rowState.
*/ */
read_pins_t RowScanner_SPIShiftRegisters::scan(read_pins_mask_t& rowEnd)
read_pins_t RowScanner_SPIShiftRegisters::scan(uint8_t& keyCount)
{ {
read_pins_t rowState = 0; read_pins_t rowState = 0;


//strobe row off //strobe row off
digitalWrite(STROBE_PIN, LOW); digitalWrite(STROBE_PIN, LOW);


rowEnd = ROW_END;
keyCount = KEY_COUNT;


//for testing breadboard, clear unpowered pins
rowState &= 0b01010001000100010001000100010001; //todo
//for testing on breadboard, clear unpowered pins
rowState &= 0b11110001000100010001000100010001; //todo


return rowState; return rowState;
} }

+ 2
- 3
src/RowScanner_SPIShiftRegisters.h 查看文件

call begin() from setup() call begin() from setup()


Upto 4 shift registers can be in a daisy chained. Upto 4 shift registers can be in a daisy chained.
The maximum keys per row is 31, because Arduino's largest type is 32 bits and rowEnd consumes the last bit.


The shift registers are active high: The shift registers are active high:
10k pull-down resistors are grounded 10k pull-down resistors are grounded
private: private:
static const uint8_t SHIFT_LOAD; //controller's pin number that is connected to shift register's SHIFT_LOAD pin static const uint8_t SHIFT_LOAD; //controller's pin number that is connected to shift register's SHIFT_LOAD pin
const uint8_t STROBE_PIN; //Arduino pin number connected to this row const uint8_t STROBE_PIN; //Arduino pin number connected to this row
const read_pins_mask_t ROW_END; //bitwise, 1 bit marks positioned after last key of row
const uint8_t BYTE_COUNT; //number of bytes to read from shift registers const uint8_t BYTE_COUNT; //number of bytes to read from shift registers
uint8_t KEY_COUNT;
public: public:
RowScanner_SPIShiftRegisters(const uint8_t STROBE_PIN, uint8_t KEY_COUNT); RowScanner_SPIShiftRegisters(const uint8_t STROBE_PIN, uint8_t KEY_COUNT);
virtual read_pins_t scan(read_pins_mask_t& rowEnd);
virtual read_pins_t scan(uint8_t& KEY_COUNT);
void begin(); void begin();
}; };
#endif #endif

+ 3
- 3
src/Row_ShiftRegisters.cpp 查看文件

{ {
//these variables are all bitwise, one bit per key //these variables are all bitwise, one bit per key
read_pins_t rowState; //1 means pressed, 0 means released read_pins_t rowState; //1 means pressed, 0 means released
read_pins_mask_t rowEnd; //1 bit marks positioned after last key of row
uint8_t keyCount;
read_pins_t debouncedChanged; //1 means debounced changed read_pins_t debouncedChanged; //1 means debounced changed


rowState = scanner.scan(rowEnd);
rowState = scanner.scan(keyCount);
debouncedChanged = debouncer.debounce(rowState, debounced); debouncedChanged = debouncer.debounce(rowState, debounced);
pressRelease(rowEnd, debouncedChanged);
pressRelease(keyCount, debouncedChanged);
} }


void Row_ShiftRegisters::begin() void Row_ShiftRegisters::begin()

+ 13
- 3
src/Row_uC.cpp 查看文件

{ {
//these variables are all bitwise, one bit per key //these variables are all bitwise, one bit per key
read_pins_t rowState; //1 means pressed, 0 means released read_pins_t rowState; //1 means pressed, 0 means released
read_pins_mask_t rowEnd; //1 bit marks positioned after last key of row
uint8_t keyCount;
read_pins_t debouncedChanged; //1 means debounced changed read_pins_t debouncedChanged; //1 means debounced changed


rowState = scanner.scan(rowEnd);
rowState = scanner.scan(keyCount);
/*
Keyboard.print(" keyCount=");
Keyboard.print(keyCount);
Keyboard.print(" rowState=");
Keyboard.print(rowState);
*/
debouncedChanged = debouncer.debounce(rowState, debounced); debouncedChanged = debouncer.debounce(rowState, debounced);
pressRelease(rowEnd, debouncedChanged);
/*
Keyboard.print(" debounced=");
Keyboard.print(debounced);
*/
pressRelease(keyCount, debouncedChanged);
} }

+ 4
- 12
src/config_keybrd.h 查看文件

#define CONFIG_KEYBRD_H #define CONFIG_KEYBRD_H
#include <inttypes.h> #include <inttypes.h>


/* size of read_pins_t and read_pins_mask_t depends on the maximum number of pins scanned by RowScanner.
By default, read_pins_t and read_pins_mask_t are set to the largest type.
/* size of read_pins_t depends on the maximum number of pins scanned by RowScanner.
By default, read_pins_t is set to the largest type.
If your 8-bit AVR is running low on memory, using a smaller type saves SRAM. If your 8-bit AVR is running low on memory, using a smaller type saves SRAM.
Using smaller types on a 32-bit uC (Teensy LC) would accomplish nothing. Using smaller types on a 32-bit uC (Teensy LC) would accomplish nothing.
*/ */
For RowScanner_SPIShiftRegisters, RowScanner_SPIShiftRegisters::KEY_COUNT For RowScanner_SPIShiftRegisters, RowScanner_SPIShiftRegisters::KEY_COUNT
For RowScanner_PinsBitwise, cover the last 1 bit in RowScanner_PinsBitwise::strobePin For RowScanner_PinsBitwise, cover the last 1 bit in RowScanner_PinsBitwise::strobePin
*/ */
typedef uint8_t read_pins_t;
//typedef uint8_t read_pins_t;
//typedef uint16_t read_pins_t; //typedef uint16_t read_pins_t;
//typedef uint32_t read_pins_t;

/* read_pins_mask_t is only used for rowMask and rowEnd, which extends one bit beyond the last col pin.
uncomment typedef that covers one bit beyond the last col pin.
This could be the same typedef as read_pins_t, or the next larger typedef.
*/
typedef uint8_t read_pins_mask_t;
//typedef uint16_t read_pins_mask_t;
//typedef uint32_t read_pins_mask_t;
typedef uint32_t read_pins_t;


/* SAMPLE_COUNT = 4 is very reliable for a keyboard. /* SAMPLE_COUNT = 4 is very reliable for a keyboard.
Split keyboards with a long connecting wire or in environment with Split keyboards with a long connecting wire or in environment with

二进制
tutorials/images/bend_diodes_en_masse2.JPG 查看文件


二进制
tutorials/images/bend_diodes_en_masse3.JPG 查看文件


二进制
tutorials/images/breadboard_keyboard_2x2_crossColumns.jpg 查看文件