combined lanc+PS/2 controller possible?

Hi ,

I successfully built a Lanc-controller with Arduino Leonardo, using code from this site (thanks, martin!):

Now I would like the same Arduino board to send PS/2 keyboard messages (function keys) to an audio-recorder.

Question 1: Is this possible? Or is there a contradiction between the two protocols (you see, I´m new..)

The audio recorder needs PS/2, not USB keyboard messages. I want to send F10 for rec, alternated with F7 for stop, from the same switch. I´m pretty sure, that´s possible. I looked all over the net, but did not find a simple solution for arduino behaving like a PS/2 keyboard. Maybe too much info and I did not get the right one...

Question 2: how should the code for sending PS/2 messages "F10" in alternation with "F7" look like?

Thanks in advance
Klaus

So I solved the problem of emulating a PS/2 keyboard, using this code

#include "ps2dev.h" // to emulate a PS/2 device

PS2dev keyboard(3,2); // PS2dev object (2:data, 3:clock)
int enabled = 0; // pseudo variable for state of "keyboard"

void ack() {
  //acknowledge commands
  while(keyboard.write(0xFA));
}

int keyboardcommand(int command) {
  unsigned char val;
  switch (command) {
  case 0xFF: //reset
    ack();
    //the while loop lets us wait for the host to be ready
    while(keyboard.write(0xAA)!=0);
    break;
  case 0xFE: //resend
    ack();
    break;
  case 0xF6: //set defaults
    //enter stream mode
    ack();
    break;
  case 0xF5: //disable data reporting
    //FM
    enabled = 0;
    ack();
    break;
  case 0xF4: //enable data reporting
    //FM
    enabled = 1;
    ack();
    break;
  case 0xF3: //set typematic rate
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  case 0xF2: //get device id
    ack();
    keyboard.write(0xAB);
    keyboard.write(0x83);
    break;
  case 0xF0: //set scan code set
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  case 0xEE: //echo
    //ack();
    keyboard.write(0xEE);
    break;
  case 0xED: //set/reset LEDs
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  }
}

void setup() {
  // send the keyboard start up
  while(keyboard.write(0xAA)!=0);
  delay(10);
}

void loop() {
  unsigned char c;
  //if host device wants to send a command:
  if( (digitalRead(3)==LOW) || (digitalRead(2) == LOW)) {
    while(keyboard.read(&c)) ;
    keyboardcommand(c);
  }
  else{ //send keypresses accordingly using scancodes
  // secancodes: http://www.computer-engineering.org/ps2keyboard/scancodes2.html
  keyboard.write(0x1C); // \
  keyboard.write(0xF0); //  |- send 'a'
  keyboard.write(0x1C); // /
  delay (1000); // wait 1 second
  }
}

and the lanc controller using this code

/*
SIMPLE LANC REMOTE
Version 1.0
Sends LANC commands to the LANC port of a video camera.
Tested with a BMCC and BMPCC.
For the interface circuit interface see 
http://controlyourcamera.blogspot.com/2011/02/arduino-controlled-video-recording-over.html
Feel free to use this code in any way you want.
2011, Martin Koch, adapted for Blackmagic cameras by klaus erharter

"LANC" is a registered trademark of SONY.
CANON calls their LANC compatible port "REMOTE".
*/

#define cmdPin 7 
#define lancPin 11
#define recButton 6
#define irisDecrementButton 5
#define IrisIncrementButton 4
#define focusNearButton 3
#define focusFarButton 2
int cmdRepeatCount;
int bitDuration = 104; //Duration of one LANC bit in microseconds. 


//LANC commands byte 0 + byte 1
//Tested with Canon XF300

//Start-stop video recording
boolean REC[] = {LOW,LOW,LOW,HIGH,HIGH,LOW,LOW,LOW,   LOW,LOW,HIGH,HIGH,LOW,LOW,HIGH,HIGH}; //18 33

//Iris increment
boolean IRIS_INCREMENT[] = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW,   LOW,HIGH,LOW,HIGH,LOW,HIGH,LOW,HIGH}; //28 55


//Iris decrement
boolean IRIS_DECREMENT[] = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW,   LOW,HIGH,LOW,HIGH,LOW,LOW,HIGH,HIGH}; //28 53


//Focus control. Camera must be switched to manual focus
boolean FOCUS_NEAR[] = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW,   LOW,HIGH,LOW,LOW,LOW,HIGH,HIGH,HIGH}; //28 47
boolean FOCUS_FAR[] = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW,   LOW,HIGH,LOW,LOW,LOW,HIGH,LOW,HIGH}; //28 45

//boolean FOCUS_AUTO[] = {LOW,LOW,HIGH,LOW,HIGH,LOW,LOW,LOW,   LOW,HIGH,LOW,LOW,LOW,LOW,HIGH,HIGH}; //28 43





void setup() {

 pinMode(lancPin, INPUT); //listens to the LANC line
 pinMode(cmdPin, OUTPUT); //writes to the LANC line

 pinMode(recButton, INPUT); //start-stop recording button
        digitalWrite(recButton, HIGH); //turn on an internal pull up resistor
        pinMode(irisDecrementButton, INPUT); 
        digitalWrite(irisDecrementButton, HIGH);
        pinMode(IrisIncrementButton, INPUT); 
        digitalWrite(IrisIncrementButton, HIGH);
        pinMode(focusNearButton, INPUT); 
        digitalWrite(focusNearButton, HIGH);
        pinMode(focusFarButton, INPUT); 
        digitalWrite(focusFarButton, HIGH);
        
        digitalWrite(cmdPin, LOW); //set LANC line to +5V
        delay(5000); //Wait for camera to power up completly
        bitDuration = bitDuration - 8; //Writing to the digital port takes about 8 microseconds so only 96 microseconds are left for each bit
}

void loop() {
  
  
   if (!digitalRead(recButton)) {
    lancCommand(REC); 
  }
  
  if (!digitalRead(IrisIncrementButton)) {
    lancCommand(IRIS_INCREMENT); 
  }
  
  if (!digitalRead(irisDecrementButton)) {
    lancCommand(IRIS_DECREMENT); 
  }
  
  if (!digitalRead(focusNearButton)) {
    lancCommand(FOCUS_NEAR); 
  }
  
  if (!digitalRead(focusFarButton)) {
    lancCommand(FOCUS_FAR); 
  }
}



void lancCommand(boolean lancBit[]) {
       
        cmdRepeatCount = 0;
  
   while (cmdRepeatCount < 5) {  //repeat 5 times to make sure the camera accepts the command

                while (pulseIn(lancPin, HIGH) < 5000) {   
                  //"pulseIn, HIGH" catches any 0V TO +5V TRANSITION and waits until the LANC line goes back to 0V 
                  //"pulseIn" also returns the pulse duration so we can check if the previous +5V duration was long enough (>5ms) to be the pause before a new 8 byte data packet
                  //Loop till pulse duration is >5ms
                }

   //LOW after long pause means the START bit of Byte 0 is here
   delayMicroseconds(bitDuration);  //wait START bit duration

   //Write the 8 bits of byte 0 
                        //Note that the command bits have to be put out in reverse order with the least significant, right-most bit (bit 0) first
                        for (int i=7; i>-1; i--) {
     digitalWrite(cmdPin, lancBit[i]);  //Write bits. 
     delayMicroseconds(bitDuration); 
                        }
   
                        //Byte 0 is written now put LANC line back to +5V
                        digitalWrite(cmdPin, LOW);
                        delayMicroseconds(10); //make sure to be in the stop bit before byte 1
                        
                        while (digitalRead(lancPin)) { 
                          //Loop as long as the LANC line is +5V during the stop bit
                        }

                        //0V after the previous stop bit means the START bit of Byte 1 is here
         delayMicroseconds(bitDuration);  //wait START bit duration
      
         //Write the 8 bits of Byte 1
                        //Note that the command bits have to be put out in reverse order with the least significant, right-most bit (bit 0) first
                        for (int i=15; i>7; i--) {
              digitalWrite(cmdPin,lancBit[i]);  //Write bits 
             delayMicroseconds(bitDuration);
                        }
 
                        //Byte 1 is written now put LANC line back to +5V
                        digitalWrite(cmdPin, LOW); 

   cmdRepeatCount++;  //increase repeat count by 1
   
   /*Control bytes 0 and 1 are written, now don’t care what happens in Bytes 2 to 7
   and just wait for the next start bit after a long pause to send the first two command bytes again.*/
  

 }//While cmdRepeatCount < 5
}

Now my question: is it possible to run these two codes at the sometime?
How should that be accomplished?

Or should I post in the programming section?
Many thanks
Klaus

It should be as simple as combining the setup functions, loop functions and just drop-in everything else. Make sure they use different pins, or have it so that the same pins are called to do the same thing I.E open/close shutter, take photo, things like that.

Thanks a lot, that makes sense!

Now I´m struggling defining a one button control in the PS/2 code, I´ll post it also in the programming forum.
In the PS/2 dev code above, the loop tells to automatically write the letter "A" if the host is not sending.
Now what I try to accomplish is to push a button so that it writes the letter .

Should be simple. Not for me...

A keyboard button or a regular tactile button?

regular tactile button.

Ok simple. There are two types of button setups, normally HIGH and normally LOW.

(VCC) ------ | Button | -----={ Arduino Pin }=-----(Resistor 10K) ------ (GND): Normally LOW

(VCC) ------(Resistor 10K)-----={ Arduino Pin }=-----| Button | --------(GND): Normally HIGH

Simple Code with Debounce:

const byte LED = 13;
const byte Button = 2; // use array for multiple buttons. "= {2,3,4,5};"
byte ButtonState;  // use array for the multiple button states
byte lastState = LOW; //-------------------------
unsigned long oldTime = 0; //-------------------------

// **Fill in for other buttons. Hint: use a for loop
void setup() {
  pinMode(LED, OUTPUT);
  pinMode(Button, INPUT);
}

void loop() {
  ButtonState = digitalRead(Button);

  if(ButtonState && ButtonState != lastState) 
  {
    oldTime = millis();
    lastState = ButtonState;
  }

  if((millis() - oldTime ) > 50UL) 
  {
    if(ButtonState)  // if button is pressed and state is HIGH 
    {
      // Do something here
      digitalWrite(LED, HIGH);
    }
    else 
    {
      // Do something else
      digitalWrite(LED, LOW);
    }
  }
}

Thanks again.

I guess, my problem is to make this button work inside the ps/2 code.
The attached code should send "a" when pressing the button. it doesn´t.
When I define a LED Pin inside this PS/2 code, I can make the code working (I attach the arduino to the PC, and by pushing the button the LED turns on), and I can make the "A"s be written, if I grey out " if (buttonState == HIGH)" in the loop.
But making the button write the letter - nope.

#include "ps2dev.h" // to emulate a PS/2 device

const int buttonPin = 6;    
int buttonState = 0;  

PS2dev keyboard(3,2); // PS2dev object (2:data, 3:clock)
int enabled = 0; // pseudo variable for state of "keyboard"

void ack() {
  //acknowledge commands
  while(keyboard.write(0xFA));
}

int keyboardcommand(int command) {
  unsigned char val;
  switch (command) {
  case 0xFF: //reset
    ack();
    //the while loop lets us wait for the host to be ready
    while(keyboard.write(0xAA)!=0);
    break;
  case 0xFE: //resend
    ack();
    break;
  case 0xF6: //set defaults
    //enter stream mode
    ack();
    break;
  case 0xF5: //disable data reporting
    //FM
    enabled = 0;
    ack();
    break;
  case 0xF4: //enable data reporting
    //FM
    enabled = 1;
    ack();
    break;
  case 0xF3: //set typematic rate
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  case 0xF2: //get device id
    ack();
    keyboard.write(0xAB);
    keyboard.write(0x83);
    break;
  case 0xF0: //set scan code set
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  case 0xEE: //echo
    //ack();
    keyboard.write(0xEE);
    break;
  case 0xED: //set/reset LEDs
    ack();
    keyboard.read(&val); //do nothing with the rate
    ack();
    break;
  }
}

void setup() {  

  pinMode(buttonPin, INPUT);   
 while(keyboard.write(0xAA)!=0);
 delay(10);
}

void loop() {
  unsigned char c;
  buttonState = digitalRead(buttonPin);
  
   if( (digitalRead(3)==LOW) || (digitalRead(2) == LOW)) {
    while(keyboard.read(&c)) ;
    keyboardcommand(c);
  }
  else
  if (buttonState == HIGH)
  {     
  
     keyboard.write(0x1C); // \
  keyboard.write(0xF0); //  |- send 'a'
  keyboard.write(0x1C); // /
  delay (1000); // wait 1 second
  }
 
}

reposted in the programming sub forum.

thanks.