Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <Keypad.h>
- #include <U8g2lib.h>
- #include <SPI.h>
- #include <Wire.h>
- U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0);
- // Accompanying code for Retrokits RK005 MIDI command keypad
- // more info on the 4x4 keypad an it's workings:
- // https://iamzxlee.wordpress.com/2013/07/24/4x4-matrix-keypad/
- // example seller on aliexpress:
- // https://www.aliexpress.com/item/4x4-Matrix-Keyboard-Keypad-Module-Use-Key-PIC-AVR-Stamp-Sml-4-4-Plastic-Keys-Switch/32828049888.html
- // Arduino Nano with CH340 search results:
- // The CH340 is the onboard serial driver which the RK005 supports
- // https://www.aliexpress.com/wholesale?catId=0&SearchText=ch340+arduino+nano
- // OLED for some fancy display shizzle, connect to GND, 5V, port A5(SCL) and A6(SDA):
- // https://www.aliexpress.com/item/1pcs-0-91-inch-OLED-module-0-91-white-OLED-128X32-OLED-LCD-LED-Display-Module/32803096466.html
- const byte ROWS = 4; // Pad with four rows
- const byte COLS = 4; // and four columns
- // Define the Keymap
- char keys[ROWS][COLS] = {
- {'1','4','7','*'},
- {'2','5','8','0'},
- {'3','6','9','#'},
- {'A','B','C','D'}
- };
- // arduino connection pins
- // pins 9 and 8 were not defined as PBx pins hence the inconsistent numbering ( * sigh * )
- // pins marking on board are D9,D8,D7,D6, D5,D4,D3,D2
- byte rowPins[ROWS] = { 9,8,PD7,PD6};
- byte colPins[COLS] = {PD5,PD4,PD3,PD2};
- // var definitions for keypad
- // holds typed number
- int keyval=0;
- // holds global midi channel
- byte midichannel=0;
- byte keymode=0;
- // holds pad keymode
- // just 2 defined in this example:
- // A = programchange
- // C = midi channel change
- // # concludes the number pressing and sends a command
- bool dispUpdate=false;
- bool clock_running=false;
- long currentTime=0;
- byte pc=0;
- byte nt=0;
- // Create the Keypad
- Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
- #define ledpin 13
- // LED goes on when in 'number enter' mode and goes off when # is pressed
- void setup()
- {
- pinMode(ledpin,OUTPUT);
- // RK005 can connect with the CH340 serial chip on 38400KBps
- // easier then the 31250 midi speed for debugging your sketch
- // on a standard serial monitor
- Serial.begin(38400);
- while (!Serial) {
- // wait for serial to become available
- }
- u8g2.begin();
- u8g2.clearBuffer(); // clear the internal memory
- // u8g2.setFont(u8g2_font_6x12_t_cyrillic);
- // choose a suitable font at https://github.com/olikraus/u8g2/wiki/fntlistall
- u8g2.setFont(u8g2_font_fub20_tf);
- u8g2.drawStr(0,31,"READY");
- dispOver();
- }
- // main loop for checking keypad
- void loop(){
- if(dispUpdate){
- if((millis()-currentTime)>1500){
- dispUpdate=false;
- u8g2.clearBuffer();
- u8g2.setFont(u8g2_font_6x12_t_cyrillic);
- u8g2.drawStr(0,19,"MIDI KEYPAD");
- if(!clock_running){
- u8g2.drawStr(90,19,"STOP");
- }else{
- u8g2.drawStr(90,19,"PLAY");
- }
- u8g2.setCursor(0,30);
- u8g2.print("Patch:"+String(pc+1)+" MIDI CH:"+String(midichannel+1));
- u8g2.sendBuffer();
- if(nt>0){ // there is a note on, off it
- byte buf[3]={0x80+midichannel,nt,100};
- Serial.write(buf,3);
- nt=0; // notes are off
- }
- }
- }
- char key = kpd.getKey();
- if (key != NO_KEY)
- {
- // is it numeric:
- if ( (key >= '0') && (key<= '9') ){
- dispUpdate=false; // prevent timeout on big display
- currentTime = millis(); // reset key timeout
- digitalWrite(ledpin, HIGH);
- // add the numeric keys and multiply a possible former key by ten
- keyval= keyval *10;
- // key is a ASCII keycode 0 so deduct '0' means: '0'is actually 0
- keyval+= (key-'0'); // add it to the existing value
- if(keyval>128){
- setSubScreen("INVALID",true);
- keyval=0;
- return;
- }
- if(keymode==2){
- setSubScreen("CH:"+String(keyval),false);
- }
- if(keymode==0){
- setSubScreen("PC:"+String(keyval),false);
- }
- if(keymode==1){
- setSubScreen("NT:"+String(keyval),false);
- }
- }
- if ( key == '#') // command close, end our key group
- {
- digitalWrite(ledpin, LOW);
- if(keymode==0){ // A = keymode 0 (Program Change)
- // set patch (deduct 1: 1-128 -> 0-127 internally )
- // clamp the values in midi spec 0-127
- pc=(byte)max(0,min(127,keyval-1));
- byte buf[2]={0xC0+midichannel,pc};
- Serial.write(buf,2);
- setSubScreen( "P"+String(pc+1)+"/C"+String(midichannel+1),true);
- }
- if(keymode==1){ // B = keymode 1 (Note Send)
- // set note (deduct 1: 1-128 -> 0-127 internally )
- // clamp the values in midi spec 0-127
- if(nt>0){ // there is a note on, off it first
- byte obuf[3]={0x80+midichannel,nt,100};
- Serial.write(obuf,3);
- }
- nt=(byte)max(0,min(127,keyval-1));
- byte buf[3]={0x90+midichannel,nt,100};
- Serial.write(buf,3);
- setSubScreen("N"+String(nt+1)+"/C"+String(midichannel+1),true);
- }
- if(keymode==2){ // C = keymode 2 (MIDI Channel)
- // set channel, (deduct 1: 1-16 -> 0-15 internally )
- midichannel=(byte)max(0,min(15,keyval-1));
- setSubScreen("CH:"+String(midichannel+1)+" OK",true);
- //keymode = 0; // after midi channel change, reset to program change input mode
- }
- keyval=0;//reset for next input
- return;
- }
- // ------------------------------------
- if ( key == '*'){
- // cancel input
- if(keyval>0){
- setSubScreen("CANCEL",true);
- keyval=0;
- }else{
- if(keymode==1){
- // all notes off
- setSubScreen("NT PANIC",true);
- byte offbuf[48];
- for(byte i=0;i<48;i+=3){
- offbuf[i]=0xB0+(i/3);
- offbuf[i+1]=123;
- offbuf[i+2]=0;
- }
- Serial.write(offbuf,48);
- }
- }
- }
- // ------------------------------------
- if ( key == 'A'){
- // set to 'MIDI Patch change' mode
- keymode=0;
- keyval=0;
- setSubScreen("PCHANGE",true);
- }
- // ------------------------------------
- if ( key == 'B'){
- // quick note send
- keymode=1;
- keyval=0;
- setSubScreen("NOTE ON",true);
- }
- // ------------------------------------
- if ( key == 'C'){
- // set to 'MIDI Channel change' mode
- keymode = 2;
- keyval=0;
- setSubScreen("CHANNEL",true);
- }
- // ------------------------------------
- if ( key == 'D'){
- // send clock start/stop
- if(!clock_running){
- // send clock start
- Serial.write(0xFA);
- setSubScreen("START",true);
- }else{
- // send clock stop
- Serial.write(0xFC);
- setSubScreen("STOP",true);
- }
- clock_running=!clock_running;
- }
- }
- }
- void setSubScreen(String message,bool tmout){
- u8g2.clearBuffer();
- u8g2.setFont(u8g2_font_fub20_tf);
- u8g2.setCursor(0,31);
- u8g2.print(message);
- u8g2.sendBuffer();
- if(tmout){
- dispOver();
- }else{
- u8g2.sendBuffer();
- }
- }
- // this function sends the screen of a key status update and
- // sets the timeout function to revert to the overview screen
- void dispOver(){
- u8g2.sendBuffer();
- dispUpdate=true;
- currentTime = millis();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement