Add SN74x154 driver and convert AL1 custom matrix (#16331)
This commit is contained in:
		
							parent
							
								
									588abd24b5
								
							
						
					
					
						commit
						2d9c3f9a89
					
				
					 5 changed files with 196 additions and 74 deletions
				
			
		
							
								
								
									
										58
									
								
								drivers/gpio/sn74x154.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								drivers/gpio/sn74x154.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | |||
| /* Copyright 2022
 | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #include "sn74x154.h" | ||||
| #include "gpio.h" | ||||
| 
 | ||||
| #define ADDRESS_PIN_COUNT 4 | ||||
| 
 | ||||
| #ifndef SN74X154_ADDRESS_PINS | ||||
| #    error sn74x154: no address pins defined! | ||||
| #endif | ||||
| 
 | ||||
| static const pin_t address_pins[ADDRESS_PIN_COUNT] = SN74X154_ADDRESS_PINS; | ||||
| 
 | ||||
| void sn74x154_init(void) { | ||||
|     for (int i = 0; i < ADDRESS_PIN_COUNT; i++) { | ||||
|         setPinOutput(address_pins[i]); | ||||
|         writePinLow(address_pins[i]); | ||||
|     } | ||||
| 
 | ||||
| #if defined(SN74X154_E0_PIN) | ||||
|     setPinOutput(SN74X154_E0_PIN); | ||||
|     writePinHigh(SN74X154_E0_PIN); | ||||
| #endif | ||||
| 
 | ||||
| #if defined(SN74X154_E1_PIN) | ||||
|     setPinOutput(SN74X154_E1_PIN); | ||||
|     writePinHigh(SN74X154_E1_PIN); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void sn74x154_set_enabled(bool enabled) { | ||||
| #if defined(SN74X154_E0_PIN) | ||||
|     writePin(SN74X154_E0_PIN, !enabled); | ||||
| #endif | ||||
| #if defined(SN74X154_E1_PIN) | ||||
|     writePin(SN74X154_E1_PIN, !enabled); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void sn74x154_set_addr(uint8_t address) { | ||||
|     for (int i = 0; i < ADDRESS_PIN_COUNT; i++) { | ||||
|         writePin(address_pins[i], address & (1 << i)); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										48
									
								
								drivers/gpio/sn74x154.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								drivers/gpio/sn74x154.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | |||
| /* Copyright 2022
 | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| #include <stdbool.h> | ||||
| 
 | ||||
| /**
 | ||||
|  * Driver for 74x154 4-to-16 decoder/demultiplexer with inverting outputs | ||||
|  * https://assets.nexperia.com/documents/data-sheet/74HC_HCT154.pdf
 | ||||
|  */ | ||||
| 
 | ||||
| /**
 | ||||
|  * Initialize the address and output enable pins. | ||||
|  */ | ||||
| void sn74x154_init(void); | ||||
| 
 | ||||
| /**
 | ||||
|  * Set the enabled state. | ||||
|  * | ||||
|  * When enabled is true, pulls the E0 and E1 pins low. | ||||
|  * | ||||
|  * \param enabled The enable state to set. | ||||
|  */ | ||||
| void sn74x154_set_enabled(bool enabled); | ||||
| 
 | ||||
| /**
 | ||||
|  * Set the output pin address. | ||||
|  * | ||||
|  * The selected output pin will be pulled low, while the remaining output pins will be high. | ||||
|  * | ||||
|  * \param address The address to set, from 0 to 15. | ||||
|  */ | ||||
| void sn74x154_set_addr(uint8_t address); | ||||
|  | @ -30,6 +30,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. | |||
| #define MATRIX_ROWS 6 | ||||
| #define MATRIX_COLS 16 | ||||
| 
 | ||||
| #define MATRIX_ROW_PINS { C7, B1, B2, C6, B4, B5 } | ||||
| 
 | ||||
| #define SN74X154_ADDRESS_PINS { D4, D5, D6, D7 } | ||||
| #define SN74X154_E1_PIN D3 | ||||
| 
 | ||||
| #define LED_NUM_LOCK_PIN D0 | ||||
| #define LED_CAPS_LOCK_PIN B7 | ||||
| #define LED_SCROLL_LOCK_PIN D1 | ||||
|  |  | |||
|  | @ -1,91 +1,101 @@ | |||
| /* Copyright 2022
 | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| #include "matrix.h" | ||||
| 
 | ||||
| #include "gpio.h" | ||||
| #include "sn74x154.h" | ||||
| 
 | ||||
| static uint8_t read_rows(void) { | ||||
|     return (readPin(C7) ? 0 : 1) | | ||||
|            (readPin(B1) ? 0 : 2) | | ||||
|            (readPin(B2) ? 0 : 4) | | ||||
|            (readPin(C6) ? 0 : 8) | | ||||
|            (readPin(B4) ? 0 : 16) | | ||||
|            (readPin(B5) ? 0 : 32); | ||||
| } | ||||
| static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; | ||||
| 
 | ||||
| /* All columns use a 74HC154 4-to-16 demultiplexer.
 | ||||
|  * D3 is the enable pin, must be set high to use it. | ||||
|  * | ||||
|  *     A3   A2   A1   A0 | ||||
|  *     D7   D6   D5   D4 | ||||
|  * 0:   0    0    0    0 | ||||
|  * 1:   0    0    0    1 | ||||
|  * 2:   0    0    1    0 | ||||
|  * 3:   0    0    1    1 | ||||
|  * 4:   0    1    0    0 | ||||
|  * 5:   0    1    0    1 | ||||
|  * 6:   0    1    1    0 | ||||
|  * 7:   0    1    1    1 | ||||
|  * 8:   1    0    0    0 | ||||
|  * 9:   1    0    0    1 | ||||
|  * 10:  1    0    1    0 | ||||
|  * 11:  1    0    1    1 | ||||
|  * 12:  1    1    0    0 | ||||
|  * 13:  1    1    0    1 | ||||
|  * 14:  1    1    1    0 | ||||
|  * 15:  1    1    1    1 | ||||
|  */ | ||||
| static void select_col(uint8_t col) { | ||||
|     writePinLow(D3); | ||||
| 
 | ||||
|     writePin(D4, (col & 1)); | ||||
|     writePin(D5, (col & 2)); | ||||
|     writePin(D6, (col & 4)); | ||||
|     writePin(D7, (col & 8)); | ||||
|     sn74x154_set_addr(col); | ||||
| } | ||||
| 
 | ||||
| static void  unselect_cols(void) { | ||||
|     writePinHigh(D3); | ||||
| static void init_pins(void) { | ||||
|     for (uint8_t x = 0; x < MATRIX_ROWS; x++) { | ||||
|         setPinInputHigh(row_pins[x]); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col) { | ||||
|     bool matrix_changed = false; | ||||
| 
 | ||||
|     // Select col and wait for col seleciton to stabilize
 | ||||
|     select_col(current_col); | ||||
|     matrix_io_delay(); | ||||
| 
 | ||||
|     // For each row...
 | ||||
|     for (uint8_t row_index = 0; row_index < MATRIX_ROWS; row_index++) { | ||||
|         // Store last value of row prior to reading
 | ||||
|         matrix_row_t last_row_value = current_matrix[row_index]; | ||||
| 
 | ||||
|         // Check row pin state
 | ||||
|         if (readPin(row_pins[row_index]) == 0) { | ||||
|             // Pin LO, set col bit
 | ||||
|             current_matrix[row_index] |= (MATRIX_ROW_SHIFTER << current_col); | ||||
|         } else { | ||||
|             // Pin HI, clear col bit
 | ||||
|             current_matrix[row_index] &= ~(MATRIX_ROW_SHIFTER << current_col); | ||||
|         } | ||||
| 
 | ||||
|         // Determine if the matrix changed state
 | ||||
|         if ((last_row_value != current_matrix[row_index]) && !(matrix_changed)) { | ||||
|             matrix_changed = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return matrix_changed; | ||||
| } | ||||
| 
 | ||||
| void matrix_init_custom(void) { | ||||
|     /* 74HC154 col pin configuration
 | ||||
|      * pin:     D3  D7  D6  D5  D4 | ||||
|      * row: off  0   x   x   x   x | ||||
|      *      0    1   0   0   0   0 | ||||
|      *      1    1   0   0   0   1 | ||||
|      *      2    1   0   0   1   0 | ||||
|      *      3    1   0   0   1   1 | ||||
|      *      4    1   0   1   0   0 | ||||
|      *      5    1   0   1   0   1 | ||||
|      *      6    1   0   1   1   0 | ||||
|      *      7    1   0   1   1   1 | ||||
|      *      8    1   1   0   0   0 | ||||
|      *      9    1   1   0   0   1 | ||||
|      *      10   1   1   0   1   0 | ||||
|      *      11   1   1   0   1   1 | ||||
|      *      12   1   1   1   0   0 | ||||
|      *      13   1   1   1   0   1 | ||||
|      *      14   1   1   1   1   0 | ||||
|      *      15   1   1   1   1   1 | ||||
|      */ | ||||
|     setPinOutput(D3); | ||||
|     writePinHigh(D3); | ||||
| 
 | ||||
|     setPinOutput(D4); | ||||
|     setPinOutput(D5); | ||||
|     setPinOutput(D6); | ||||
|     setPinOutput(D7); | ||||
| 
 | ||||
| 
 | ||||
|     /* Row pin configuration
 | ||||
|      * | ||||
|      * row:  0  1  2  3  4  5 | ||||
|      * pin: C7 B1 B2 C6 B4 B5 | ||||
|      * | ||||
|      */ | ||||
|     setPinInputHigh(C7); | ||||
|     setPinInputHigh(B1); | ||||
|     setPinInputHigh(B2); | ||||
|     setPinInputHigh(C6); | ||||
|     setPinInputHigh(B4); | ||||
|     setPinInputHigh(B5); | ||||
|     // initialize demultiplexer
 | ||||
|     sn74x154_init(); | ||||
|     sn74x154_set_enabled(true); | ||||
|     // initialize key pins
 | ||||
|     init_pins(); | ||||
| } | ||||
| 
 | ||||
| bool matrix_scan_custom(matrix_row_t current_matrix[]) { | ||||
|     bool changed = false; | ||||
| 
 | ||||
|     for (uint8_t col = 0; col < MATRIX_COLS; col++) { | ||||
|         select_col(col); | ||||
|         matrix_io_delay(); | ||||
|         uint8_t rows = read_rows(); | ||||
| 
 | ||||
|         for (uint8_t row = 0; row < MATRIX_ROWS; row++) { | ||||
|             bool prev_bit = current_matrix[row] & ((matrix_row_t)1 << col); | ||||
|             bool curr_bit = rows & (1 << row); | ||||
| 
 | ||||
|             if (prev_bit != curr_bit) { | ||||
|                 current_matrix[row] ^= ((matrix_row_t)1 << col); | ||||
|                 changed = true; | ||||
|             } | ||||
|         } | ||||
|         unselect_cols(); | ||||
|     // Set col, read rows
 | ||||
|     for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++) { | ||||
|         changed |= read_rows_on_col(current_matrix, current_col); | ||||
|     } | ||||
| 
 | ||||
|     return changed; | ||||
|  |  | |||
|  | @ -18,4 +18,5 @@ RGBLIGHT_ENABLE = no        # Enable keyboard RGB underglow | |||
| AUDIO_ENABLE = no           # Audio output | ||||
| 
 | ||||
| CUSTOM_MATRIX = lite | ||||
| SRC += matrix.c | ||||
| VPATH += drivers/gpio | ||||
| SRC += matrix.c sn74x154.c | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Ryan
						Ryan