From 96ecff377f945dee9cd9ac00c6670f9e1377ddf5 Mon Sep 17 00:00:00 2001 From: Labrusca Date: Tue, 1 Aug 2023 15:38:12 +0800 Subject: [PATCH] update --- .gitignore | 1 + KB-m60.uf2 | Bin 23040 -> 0 bytes README.md | 9 +- prototype/main.go | 147 --------------- src/go.mod | 8 + src/is31fl3733/is31fl3733.go | 188 +++++++++++++++++++ src/is31fl3733/registers.go | 101 +++++++++++ src/main.go | 219 +++++++++++++++++++++++ tinygo/src/machine/board_m60-keyboard.go | 9 +- tinygo/targets/m60-keyboard.json | 15 +- 10 files changed, 535 insertions(+), 162 deletions(-) create mode 100644 .gitignore delete mode 100644 KB-m60.uf2 delete mode 100644 prototype/main.go create mode 100644 src/go.mod create mode 100644 src/is31fl3733/is31fl3733.go create mode 100644 src/is31fl3733/registers.go create mode 100644 src/main.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dabf36e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +prototype/is31fl3733/ \ No newline at end of file diff --git a/KB-m60.uf2 b/KB-m60.uf2 deleted file mode 100644 index 4ab6942c382ad4499b5927f11c5ea866b616832c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23040 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 D^70Ws diff --git a/README.md b/README.md index 69f9214..1a1d750 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,14 @@ # Mordecai Project Mordecai is a keyboard firmware for Makerdiary M60 Keyboard based on tinygo +## Plan +- [x] Base Keyboard function +- [x] Add is31fl3733 driver(Only PWM mode) +- [ ] Bluetooth Support +- [ ] Rewrite Golang code + ## Notice +**First, you need add some files to your TINYGOROOT** Put file folder "tinygo" in your tinygo path before building. ## build @@ -13,4 +20,4 @@ Let the keyboard into Bootloader mode, and copy the file 'KB-m60.uf2' to keyboar Enjoy! -### Test on tinygo @0.24.0 \ No newline at end of file +### Test on tinygo @0.28.1 \ No newline at end of file diff --git a/prototype/main.go b/prototype/main.go deleted file mode 100644 index c6d192c..0000000 --- a/prototype/main.go +++ /dev/null @@ -1,147 +0,0 @@ -package main - -import ( - "machine" - "machine/usb/hid/keyboard" - //"os" - "time" -) - - -var ( - ROWS = [8]machine.Pin{machine.P0_05, machine.P0_06, machine.P0_07, machine.P0_08, machine.P1_09, machine.P1_08, machine.P0_12, machine.P0_11} - COLS = [8]machine.Pin{machine.P0_19, machine.P0_20, machine.P0_21, machine.P0_22, machine.P0_23, machine.P0_24, machine.P0_25, machine.P0_26} - - COORDS = []int{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 27,26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, - 28,29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 52,51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, - 53, 54, 55, 56, 57, 58, 59, 60, - } - - KeyNO keyboard.Keycode = 0x00 - KeyFN keyboard.Keycode = 0x00 - - KEYMAP = [...][61]keyboard.Keycode{ - { - keyboard.KeyEsc, keyboard.Key1, keyboard.Key2, keyboard.Key3, keyboard.Key4, keyboard.Key5, keyboard.Key6, keyboard.Key7, keyboard.Key8, keyboard.Key9, keyboard.Key0, keyboard.KeyMinus, keyboard.KeyEqual, keyboard.KeyBackspace, - keyboard.KeyTab, keyboard.KeyQ, keyboard.KeyW, keyboard.KeyE, keyboard.KeyR, keyboard.KeyT, keyboard.KeyY, keyboard.KeyU, keyboard.KeyI, keyboard.KeyO, keyboard.KeyP, keyboard.KeyLeftBrace, keyboard.KeyRightBrace, keyboard.KeyBackslash, - keyboard.KeyCapsLock, keyboard.KeyA, keyboard.KeyS, keyboard.KeyD, keyboard.KeyF, keyboard.KeyG, keyboard.KeyH, keyboard.KeyJ, keyboard.KeyK, keyboard.KeyL, keyboard.KeySemicolon, keyboard.KeyQuote, keyboard.KeyEnter, - keyboard.KeyModifierLeftShift, keyboard.KeyZ, keyboard.KeyX, keyboard.KeyC, keyboard.KeyV, keyboard.KeyB, keyboard.KeyN, keyboard.KeyM, keyboard.KeyComma, keyboard.KeyPeriod, keyboard.KeySlash, keyboard.KeyModifierRightShift, - keyboard.KeyModifierLeftCtrl, keyboard.KeyModifierLeftAlt, keyboard.KeyModifierLeftGUI, keyboard.KeySpace, keyboard.KeyModifierRightAlt, keyboard.KeyModifierRightGUI, KeyFN, keyboard.KeyModifierRightCtrl, - }, - - { - keyboard.KeyEsc, keyboard.KeyF1, keyboard.KeyF2, keyboard.KeyF3, keyboard.KeyF4, keyboard.KeyF5, keyboard.KeyF6, keyboard.KeyF7, keyboard.KeyF8, keyboard.KeyF9, keyboard.KeyF10, keyboard.KeyF11, keyboard.KeyF12, keyboard.KeyDelete, - KeyNO, KeyNO, keyboard.KeyUp, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, keyboard.KeyMediaVolumeDec, keyboard.KeyMediaVolumeInc, keyboard.KeyMediaMute, - KeyNO, keyboard.KeyLeft, keyboard.KeyDown, keyboard.KeyRight, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, - KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, keyboard.KeyMediaPrevTrack, keyboard.KeyMediaNextTrack, keyboard.KeyMediaPlayPause, KeyNO, - KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, - }, - } - - pressed_keys []int -) - -func Scan() ([]int, []int, []int) { - var new_keys []int - var inter_pressed_keys []int - released_keys := pressed_keys - for c, _ := range COLS{ - COLS[c].High() - for r, _ := range ROWS{ - if ROWS[r].Get() { - key := r * len(COLS) + c - inter_pressed_keys = append(inter_pressed_keys, key) - deleteIndex := IsContain(released_keys,key) - if deleteIndex != -1 { - released_keys = append(released_keys[:deleteIndex], released_keys[(deleteIndex+1):]...) - } else { - new_keys = append(new_keys, key) - } - - } - } - COLS[c].Low() - } - pressed_keys = inter_pressed_keys - return pressed_keys, released_keys, new_keys -} - -//https://blog.csdn.net/m0_37422289/article/details/103570799 CC 4.0 BY-SA -func IsContain(items []int, item int) int { - for i, eachItem := range items { - if eachItem == item { - return i - } - } - return -1 -} - -func ChkErr(n int, e error) { - if e != nil { - print("line:",n) - println(e) - //os.Exit(0) - } -} - -func main() { - btn := machine.BUTTON - btn.Configure(machine.PinConfig{Mode: machine.PinInput}) - - for i, _ := range ROWS { - ROWS[i].Configure(machine.PinConfig{Mode: machine.PinInputPulldown}) - } - for j, _ := range COLS { - COLS[j].Configure(machine.PinConfig{Mode: machine.PinOutput}) - } - - config := machine.UARTConfig{ - BaudRate: 115200, - TX: machine.UART_TX_PIN, - RX: machine.UART_RX_PIN, - } - machine.UART0.Configure(config) - - var keyboard = keyboard.New() - var layer int - layer = 0 - for { - // Press the button for entering Bootloader - if btn.Get() == false{ - machine.EnterUF2Bootloader() - } - _, released_keys, new_keys := Scan() - - for _, key := range released_keys { - if KEYMAP[layer][IsContain(COORDS,key)] == KeyFN { - layer = 0 - println("Layer 0") - continue - } - err := keyboard.Up(KEYMAP[layer][IsContain(COORDS,key)]) - ChkErr(125, err) - print("Release: ") - println(key, KEYMAP[layer][IsContain(COORDS,key)]) - } - - if len(new_keys) > 6 { - println("Max! Drop other...") - break - } - for _, key := range new_keys { - if KEYMAP[layer][IsContain(COORDS,key)] == KeyFN { - layer = 1 - println("Layer 1") - continue - } - err := keyboard.Down(KEYMAP[layer][IsContain(COORDS,key)]) - ChkErr(138, err) - print("Press: ") - println(key, KEYMAP[layer][IsContain(COORDS,key)]) - } - time.Sleep(time.Millisecond * 1) - } -} \ No newline at end of file diff --git a/src/go.mod b/src/go.mod new file mode 100644 index 0000000..e3d9b46 --- /dev/null +++ b/src/go.mod @@ -0,0 +1,8 @@ +module m60 + +go 1.20 + +require ( + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + tinygo.org/x/drivers v0.25.0 // indirect +) diff --git a/src/is31fl3733/is31fl3733.go b/src/is31fl3733/is31fl3733.go new file mode 100644 index 0000000..e286b2a --- /dev/null +++ b/src/is31fl3733/is31fl3733.go @@ -0,0 +1,188 @@ +// Package is31fl3733 provides a driver for the Lumissil IS31FL3733 matrix LED +// driver. +// +// Driver supports following layouts: +// - any custom LED matrix layout +// - Adafruit 16x12 CharliePlex LED Matrix FeatherWing (CharlieWing) +// https://www.adafruit.com/product/3163 +// +// Datasheet: +// https://www.lumissil.com/assets/pdf/core/IS31FL3733_DS.pdf +// +// This driver inspired by Adafruit Python driver: +// https://github.com/y4m-y4m/CircuitPython_IS31FL3733 +// +package is31fl3733 + +import ( + "fmt" + //"time" + + "machine" + //"math" +) + +// Device implements TinyGo driver for Lumissil IS31FL3733 matrix LED driver + + +type Device struct { + //Address uint8 + Bus *machine.I2C + + // Currently selected Page register (one of the frame registers or the + // function register) + SelectedPage uint8 + //pwm_pixels []byte + //abm_pixels []byte + pixels [192]byte +} + +func New(bus *machine.I2C, SPage uint8) Device { + return Device{ + Bus: bus, + SelectedPage: SPage, + } +} + +// Configure chip for operating as a LED matrix display +func (d *Device) Init() (err error) { + + backlightPower := machine.RGB_POWER + backlightPower.Configure(machine.PinConfig{Mode: machine.PinOutput}) + backlightPower.High() + + + err = d.SelectPage(FUNCTION_REGISTER) + if err != nil { + return fmt.Errorf("failed to init: %w", err) + } + // reset + err = d.WriteCommonReg(_RESET_REGISTER, 0x01) + if err != nil { + return fmt.Errorf("failed to init: %w", err) + } + // set software shutdown mode + err = d.WriteCommonReg(_CONFIGURATION_REGISTER, CONFIGURATION_NORMAL_OPERATION) + if err != nil { + return fmt.Errorf("failed to init: %w", err) + } + // set pullup_resistor = RESISTOR_32K & pulldown_resistor = RESISTOR_32K + err = d.WriteCommonReg(_PULLUP_RESISTOR_SELECTION_REGISTER, RESISTOR_32K) + if err != nil { + return fmt.Errorf("failed to init: %w", err) + } + err = d.WriteCommonReg(_PULLDOWN_RESISTOR_SELECTION_REGISTER, RESISTOR_32K) + if err != nil { + return fmt.Errorf("failed to init: %w", err) + } + + // init pixels + for i:=0;i<192;i++ { + d.pixels[i] = 0x01 + } + + // set brightness + err = d.WriteCommonReg(_CURRENT_CONTROL_REGISTER, 128) + if err != nil { + return fmt.Errorf("failed to init: %w", err) + } + + //err = d.SetLEDState() + //if err != nil { + // return fmt.Errorf("failed to init: %w", err) + //} + return nil +} + +// selectPage selects Page register, can be: +// - PWM registers +// - function register +func (d *Device) SelectPage(Page uint8) (err error) { + + err = d.Bus.WriteRegister(ADDRESS, PAGE_REGISTER_WRITE_LOCK, []byte{WRITE_LOCK_DISABLE_ONCE}) + if err != nil { + return fmt.Errorf("failed to unlock page write: %w", err) + } + err = d.Bus.WriteRegister(ADDRESS, PAGE_REGISTER, []byte{Page}) + if err != nil { + return fmt.Errorf("failed to select page %w: %w", Page, err) + } + if Page != d.SelectedPage { + d.SelectedPage = Page + } + return nil +} + +func (d *Device) WriteCommonReg(reg_addr uint8, data uint8) (err error) { + err = d.Bus.WriteRegister(ADDRESS, reg_addr, []byte{data}) + if err != nil { + return fmt.Errorf("failed to write register: %w", err) + } + return nil +} + + +// WritePagedReg selects the function register and writes data into it +func (d *Device) WritePagedReg(reg_addr uint8, data uint8) (err error) { + err = d.SelectPage(reg_addr) + if err != nil { + return err + } + err = d.Bus.WriteRegister(ADDRESS, reg_addr, []byte{data}) + if err != nil { + return fmt.Errorf("failed to write page register: %w", err) + } + return nil +} + +func (d *Device) EnableAllPixels() error { + d.SelectPage(LED_CONTROL_REGISTER) + err := d.Bus.WriteRegister(ADDRESS, LED_ONOFF_REGISTER_START, []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}) + if err != nil { + return fmt.Errorf("failed to write all pixels: %w", err) + } + d.SelectPage(PWM_REGISTER) + + data := make([]byte, 16) + for i := range data { + data[i] = 255 + } + + for i:=0;i<12;i++ { + err := d.Bus.WriteRegister(ADDRESS, uint8(i*16), data) + if err != nil { + return fmt.Errorf("failed to write all pixels: %w", err) + } + } + for i:=0;i<192;i++ { + d.pixels[i] = 255 + } + return nil +} + + +func (d *Device) Set_PWM_Pixel(index int, value [3]uint8) (err error) { + buffer := make([]byte, 192) + row := index / 16 + col := index & 15 + offset := row * 48 + col + buffer[offset] = value[1] + buffer[offset + 16] = value[0] + buffer[offset + 32] = value[2] + if index ==56 { + // No.61 and No.62 are under the space key. + // 61 + buffer[157] = value[1] + buffer[157 + 16] = value[0] + buffer[157 + 32] = value[2] + // 62 + buffer[158] = value[1] + buffer[158 + 16] = value[0] + buffer[158 + 32] = value[2] + } + err = d.SelectPage(PWM_REGISTER) + if err != nil { + return fmt.Errorf("failed to write page register: %w", err) + } + return d.Bus.WriteRegister(ADDRESS, 0x00, buffer) +} \ No newline at end of file diff --git a/src/is31fl3733/registers.go b/src/is31fl3733/registers.go new file mode 100644 index 0000000..a741f82 --- /dev/null +++ b/src/is31fl3733/registers.go @@ -0,0 +1,101 @@ +package is31fl3733 + +// Registers. Names taken from the datasheet: +// https://www.lumissil.com/assets/pdf/core/IS31FL3731_DS.pdf +const ( + // AD pin connected to GND + //I2C_ADDRESS_74 uint8 = 0x74 + // AD pin connected to SCL + //I2C_ADDRESS_75 uint8 = 0x75 + // AD pin connected to SDA + //I2C_ADDRESS_76 uint8 = 0x76 + // AD pin connected to VCC + //I2C_ADDRESS_77 uint8 = 0x77 + + ADDRESS uint8 = 0x50 + + // REGISTER DEFINITION + PAGE_REGISTER uint8 = 0xFD + PAGE_REGISTER_WRITE_LOCK uint8 = 0xFE + INTERRUPT_MASK_REGISTER uint8 = 0xF0 + INTERRUPT_STATUS_REGISTER uint8 = 0xF1 + LED_CONTROL_REGISTER uint8 = 0x00 + PWM_REGISTER uint8 = 0x01 + AUTO_BREATH_MODE_REGISTER uint8 = 0x02 + FUNCTION_REGISTER uint8 = 0x03 + + WRITE_LOCK_DISABLE_ONCE uint8 = 0xC5 + LED_ONOFF_REGISTER_START uint8 = 0x00 + LED_OPEN_REGISTER_START uint8 = 0x18 + LED_SHORT_REGISTER_START uint8 = 0x30 + + _CONFIGURATION_REGISTER uint8 = 0x00 + _CURRENT_CONTROL_REGISTER uint8 = 0x01 + _TIME_UPDATE_REGISTER uint8 = 0x0E + _PULLUP_RESISTOR_SELECTION_REGISTER uint8 = 0x0F + _PULLDOWN_RESISTOR_SELECTION_REGISTER uint8 = 0x10 + _RESET_REGISTER uint8 = 0x11 + + CONFIGURATION_SYNC_CLOCK_MASTER uint8 = 0b01000000 + CONFIGURATION_SYNC_CLOCK_SLAVE uint8 = 0b10000000 + CONFIGURATION_SYNC_CLOCK_HIGH_IMPEDANCE uint8 = 0b00000000 + CONFIGURATION_OPEN_SHORT_DETECTION_ENABLE uint8 = 0b00000100 + CONFIGURATION_OPEN_SHORT_DETECTION_DISABLE uint8 = 0b00000000 + CONFIGURATION_ABM_ENABLE uint8 = 0b00000010 + CONFIGURATION_PWM_ENABLE uint8 = 0b00000000 + CONFIGURATION_SOFTWARE_SHUTDOWN uint8 = 0b00000000 + CONFIGURATION_NORMAL_OPERATION uint8 = 0b00000001 + + AUTO_CLEAR_INTERRUPT_ENABLE uint8 = 0x08 + AUTO_CLEAR_INTERRUPT_DISABLE uint8 = 0x00 + AUTO_BREATH_INTERRUPT_ENABLE uint8 = 0x04 + AUTO_BREATH_INTERRUPT_DISABLE uint8 = 0x00 + DOT_SHORT_INTERRUPT_ENABLE uint8 = 0x02 + DOT_SHORT_INTERRUPT_DISABLE uint8 = 0x00 + DOT_OPEN_INTERRUPT_ENABLE uint8 = 0x01 + DOT_OPEN_INTERRUPT_DISABLE uint8 = 0x00 + + LED_MODE_PWM uint8 = 0x00 + LED_MODE_ABM1 uint8 = 0x01 + LED_MODE_ABM2 uint8 = 0x02 + LED_MODE_ABM3 uint8 = 0x03 + + ABM_T1_T3_210MS uint8 = 0x00 + ABM_T1_T3_420MS uint8 = 0x20 + ABM_T1_T3_840MS uint8 = 0x40 + ABM_T1_T3_1680MS uint8 = 0x60 + ABM_T1_T3_3360MS uint8 = 0x80 + ABM_T1_T3_6720MS uint8 = 0xA0 + ABM_T1_T3_13440MS uint8 = 0xC0 + ABM_T1_T3_26880MS uint8 = 0xE0 + + ABM_T2_T4_0MS uint8 = 0x00 + ABM_T2_T4_210MS uint8 = 0x02 + ABM_T2_T4_420MS uint8 = 0x04 + ABM_T2_T4_840MS uint8 = 0x06 + ABM_T2_T4_1680MS uint8 = 0x08 + ABM_T2_T4_3360MS uint8 = 0x0A + ABM_T2_T4_6720MS uint8 = 0x0C + ABM_T2_T4_13440MS uint8 = 0x0E + ABM_T2_T4_26880MS uint8 = 0x10 + + ABM_T4_53760MS uint8 = 0x12 + ABM_T4_107520MS uint8 = 0x14 + + ABM_LOOP_BEGIN_T1 uint8 = 0x00 + ABM_LOOP_BEGIN_T2 uint8 = 0x10 + ABM_LOOP_BEGIN_T3 uint8 = 0x20 + ABM_LOOP_BEGIN_T4 uint8 = 0x30 + + ABM_LOOP_END_T3 uint8 = 0x00 + ABM_LOOP_END_T1 uint8 = 0x40 + + RESISTOR_NONE uint8 = 0x00 + RESISTOR_500 uint8 = 0x01 + RESISTOR_1K uint8 = 0x02 + RESISTOR_2K uint8 = 0x03 + RESISTOR_4K uint8 = 0x04 + RESISTOR_8K uint8 = 0x05 + RESISTOR_16K uint8 = 0x06 + RESISTOR_32K uint8 = 0x07 +) \ No newline at end of file diff --git a/src/main.go b/src/main.go new file mode 100644 index 0000000..5411c10 --- /dev/null +++ b/src/main.go @@ -0,0 +1,219 @@ +package main + +import ( + "fmt" + "log" + //"container/list" + "m60/is31fl3733" + "machine" + "machine/usb/hid/keyboard" + //"os" + "time" +) + +var ( + ROWS = [8]machine.Pin{machine.P0_05, machine.P0_06, machine.P0_07, machine.P0_08, machine.P1_09, machine.P1_08, machine.P0_12, machine.P0_11} + COLS = [8]machine.Pin{machine.P0_19, machine.P0_20, machine.P0_21, machine.P0_22, machine.P0_23, machine.P0_24, machine.P0_25, machine.P0_26} + + COORDS = []int{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 27,26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, + 28,29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 52,51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, + 53, 54, 55, 56, 57, 58, 59, 60, + } + + KeyNO keyboard.Keycode = 0x00 + KeyFN keyboard.Keycode = 0x00 + + KEYMAP = [...][61]keyboard.Keycode{ + { + keyboard.KeyEsc, keyboard.Key1, keyboard.Key2, keyboard.Key3, keyboard.Key4, keyboard.Key5, keyboard.Key6, keyboard.Key7, keyboard.Key8, keyboard.Key9, keyboard.Key0, keyboard.KeyMinus, keyboard.KeyEqual, keyboard.KeyBackspace, + keyboard.KeyTab, keyboard.KeyQ, keyboard.KeyW, keyboard.KeyE, keyboard.KeyR, keyboard.KeyT, keyboard.KeyY, keyboard.KeyU, keyboard.KeyI, keyboard.KeyO, keyboard.KeyP, keyboard.KeyLeftBrace, keyboard.KeyRightBrace, keyboard.KeyBackslash, + keyboard.KeyCapsLock, keyboard.KeyA, keyboard.KeyS, keyboard.KeyD, keyboard.KeyF, keyboard.KeyG, keyboard.KeyH, keyboard.KeyJ, keyboard.KeyK, keyboard.KeyL, keyboard.KeySemicolon, keyboard.KeyQuote, keyboard.KeyEnter, + keyboard.KeyModifierLeftShift, keyboard.KeyZ, keyboard.KeyX, keyboard.KeyC, keyboard.KeyV, keyboard.KeyB, keyboard.KeyN, keyboard.KeyM, keyboard.KeyComma, keyboard.KeyPeriod, keyboard.KeySlash, keyboard.KeyModifierRightShift, + keyboard.KeyModifierLeftCtrl, keyboard.KeyModifierLeftAlt, keyboard.KeyModifierLeftGUI, keyboard.KeySpace, keyboard.KeyModifierRightAlt, keyboard.KeyMenu, KeyFN, keyboard.KeyModifierRightCtrl, + }, + + { + keyboard.KeyTilde, keyboard.KeyF1, keyboard.KeyF2, keyboard.KeyF3, keyboard.KeyF4, keyboard.KeyF5, keyboard.KeyF6, keyboard.KeyF7, keyboard.KeyF8, keyboard.KeyF9, keyboard.KeyF10, keyboard.KeyF11, keyboard.KeyF12, keyboard.KeyDelete, + KeyNO, KeyNO, keyboard.KeyUp, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, keyboard.KeyMediaVolumeDec, keyboard.KeyMediaVolumeInc, keyboard.KeyMediaMute, + KeyNO, keyboard.KeyLeft, keyboard.KeyDown, keyboard.KeyRight, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, 0xE470, 0xE46F, KeyNO, + KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, keyboard.KeyMediaPrevTrack, keyboard.KeyMediaNextTrack, keyboard.KeyMediaPlayPause, KeyNO, + KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, KeyNO, + }, + } + + pressed_keys []int +) + +func Scan() ([]int, []int, []int, error) { + var new_keys []int + var inter_pressed_keys []int + released_keys := pressed_keys + for c, _ := range COLS{ + COLS[c].High() + for r, _ := range ROWS{ + if ROWS[r].Get() { + key := r * len(COLS) + c + inter_pressed_keys = append(inter_pressed_keys, key) + deleteIndex := IsContain(released_keys,key) + if deleteIndex != -1 { + released_keys = append(released_keys[:deleteIndex], released_keys[(deleteIndex+1):]...) + } else { + new_keys = append(new_keys, key) + } + + } + } + COLS[c].Low() + time.Sleep(time.Millisecond * 2) + } + pressed_keys = inter_pressed_keys + + return pressed_keys, released_keys, new_keys, nil +} + +//https://blog.csdn.net/m0_37422289/article/details/103570799 CC 4.0 BY-SA +func IsContain(items []int, item int) int { + for i, eachItem := range items { + if eachItem == item { + return i + } + } + return -1 +} + +func ChkErr(n int, e error) { + if e != nil { + led_err := machine.LED_RED + led_err.Configure(machine.PinConfig{Mode: machine.PinOutput}) + led_err.Low() + log.Print("line: ", n) + log.Println(e) + time.Sleep(time.Millisecond * 5000) + //os.Exit(0) + machine.EnterUF2Bootloader() + } +} + +func power_init() { + power := machine.POWER_PULLUP_PIN + power.Configure(machine.PinConfig{Mode: machine.PinInputPullup}) +} + + +func main() { + //power_init() + btn := machine.BUTTON + btn.Configure(machine.PinConfig{Mode: machine.PinInput}) + + config := machine.UARTConfig{ + BaudRate: 115200, + TX: machine.UART_TX_PIN, + RX: machine.UART_RX_PIN, + } + machine.UART0.Configure(config) + + //for btn.Get() == true { + // continue + //} + + rgb := is31fl3733.New(machine.I2C0, is31fl3733.FUNCTION_REGISTER) + err := rgb.Bus.Configure(machine.I2CConfig{ + Mode: machine.I2CModeController, + Frequency: 400000, + SCL: machine.SCL_PIN, + SDA: machine.SDA_PIN, + }) + if err != nil { + println("could not configure I2C:", err) + } + + err = rgb.Init() + println("RGB init done!") + if err != nil { + println("could not init:", err) + } + err = rgb.EnableAllPixels() + if err != nil { + println("could not open lights:", err) + } + println("RGB all open!") + + led := machine.LED_BLUE + led.Configure(machine.PinConfig{Mode: machine.PinOutput}) + led.Low() + time.Sleep(time.Millisecond * 500) + led.High() + time.Sleep(time.Millisecond * 500) + + led.Low() + time.Sleep(time.Millisecond * 500) + led.High() + time.Sleep(time.Millisecond * 500) + + + for i, _ := range ROWS { + ROWS[i].Configure(machine.PinConfig{Mode: machine.PinInputPulldown}) + } + for j, _ := range COLS { + COLS[j].Configure(machine.PinConfig{Mode: machine.PinOutput}) + } + + + var kb = keyboard.New() + var layer int + layer = 0 + + + for { + // Press the button for entering Bootloader + if btn.Get() == false { + log.Println("Enter Bootloader...") + machine.EnterUF2Bootloader() + } + + _, released_keys, new_keys, err:= Scan() + if err != nil { + log.Println(err) + } + + for _, key := range released_keys { + keycode := KEYMAP[layer][IsContain(COORDS,key)] + if keycode == KeyFN { + rgb.Set_PWM_Pixel(key, [3]uint8{0,0,0}) + layer = 0 + log.Print("Layer 0\n") + continue + } + err := rgb.Set_PWM_Pixel(key, [3]uint8{0,0,0}) + ChkErr(183, err) + err = kb.Up(keycode) + ChkErr(185, err) + fmt.Print("Release: ") + fmt.Print(key, keycode) + } + + + for _, key := range new_keys { + keycode := KEYMAP[layer][IsContain(COORDS,key)] + if keycode == KeyFN { + rgb.Set_PWM_Pixel(key, [3]uint8{255,255,0}) + layer = 1 + log.Print("Layer 1\n") + continue + } + err := rgb.Set_PWM_Pixel(key, [3]uint8{255,255,255}) + ChkErr(199, err) + err = kb.Down(keycode) + ChkErr(201, err) + fmt.Print("Press: ") + fmt.Print(key, keycode) + } + + } + kb.Release() + log.Print(fmt.Errorf("Unknow Error!")) + machine.EnterUF2Bootloader() +} diff --git a/tinygo/src/machine/board_m60-keyboard.go b/tinygo/src/machine/board_m60-keyboard.go index dfa9bad..71ccf02 100644 --- a/tinygo/src/machine/board_m60-keyboard.go +++ b/tinygo/src/machine/board_m60-keyboard.go @@ -22,7 +22,7 @@ package machine const HasLowFrequencyCrystal = true -// LEDs on the m600-keyboard (nRF52840 m.2 dev board) +// LEDs on the m60-keyboard (nRF52840 m.2 dev board) const ( LED Pin = LED_GREEN LED_GREEN Pin = P0_29 @@ -40,15 +40,15 @@ const ( QSPI_DATA3 = P1_12 ) -// LED I2C pins on the m600-keyboard (unused) +// LED I2C pins on the m60-keyboard (unused) const ( SDA_PIN = P1_05 SCL_PIN = P1_06 ) const ( - POWER = P1_04 - INTERRUPT = P1_07 + RGB_POWER = P1_04 + RGB_INTERRUPT = P1_07 ) // board @@ -76,6 +76,7 @@ const ( // Battery const ( + POWER_PULLUP_PIN = P0_28 CHARGING = P0_03 VOLTAGE = P0_02 ) diff --git a/tinygo/targets/m60-keyboard.json b/tinygo/targets/m60-keyboard.json index 1aec352..12cb21a 100644 --- a/tinygo/targets/m60-keyboard.json +++ b/tinygo/targets/m60-keyboard.json @@ -1,11 +1,6 @@ { - "inherits": ["nrf52840"], - "build-tags": ["m60_keyboard","nrf52840_reset_uf2", "softdevice", "s140v6"], - "serial": "usb", - "flash-1200-bps-reset": "true", - "flash-method": "msd", - "msd-volume-name": "M60KEYBOARD", - "msd-firmware-name": "firmware.uf2", - "uf2-family-id": "0xADA52840", - "linkerscript": "targets/circuitplay-bluefruit.ld" -} + "inherits": ["nrf52840", "nrf52840-s140v6-uf2"], + "build-tags": ["m60_keyboard"], + "serial": "usb", + "flash-method": "msd" +} \ No newline at end of file