void setup() {
}
//define multiplexor pins
#define EN 7 // D7 pin
#define S0 2 // D2 pin
#define S1 3 // D3 pin
#define S2 4 // D4 pin
#define S3 5 // D5 pin
// define screen mode directions
#define STOP 0 // multiplexer C0 pin
#define DOWN 1 // multiplexer C1 pin
#define UP 2 // multiplexer C0 pin
// define analog pin for voltage sensor
#define VSensor A0 // A0 pin
// AV-receiver low and high limits for a trigger
const int TriggerLow = 3; // if voltage is lower than the value, then the trigger is OFF
const int TriggerHigh = 7; // if voltage is higher than the value, then the trigger is ON
// projector serial connection variables
const byte numChars = 32;
char receivedChars[numChars]; //an array to store the received data
// projector state variables
boolean newData = false;
String ProjectorPowerState;
String ProjectorPreviousPowerState;
//screen constants
const int PullUpTime = 25000; // full time from lower to upper position, milliseconds
const int PushDownTime = 19500; // time that requred to push down the screen to a working position; milliseconds
void setup() {
// set digital pins mode
pinMode(S0, OUTPUT);
pinMode(S1, OUTPUT);
pinMode(S2, OUTPUT);
pinMode(S3, OUTPUT);
pinMode(EN, OUTPUT);
// initialize the multiplexer
digitalWrite(S0, LOW);
digitalWrite(S1, LOW);
digitalWrite(S2, LOW);
digitalWrite(S3, LOW);
digitalWrite(EN, HIGH);
Serial.begin(9600); // console output for debug
Serial1.begin(9600); // projector serial connection
ProjectorPreviousPowerState = "Unknown";
}
void loop() {
int volt = analogRead(VSensor); // read the input
int voltage = map(volt,0,1023, 0, 2500); // input voltage in centivolts. i.e. 3V = 300 cV
Serial.println((String)"Trigger voltage in centivolts: " + voltage);
if (Serial1.available()) {
Serial.println("Projector serial connection is available, we need to check it state");
recvWithEndMarker();
// we need to get current projector state variable from the serial output
if (newData == true) { // only if we have a new data, we need to check the state
newData = false; // reset the new data flag
ProjectorPowerState = String(receivedChars); // convert array to a sting
ProjectorPowerState.trim(); // remove \r\n
Serial.println((String)"Projector current state is '" + ProjectorPowerState + "'");
}
// now we are ready to control the projector and screen
if (ProjectorPowerState == "OK0") {
Serial.println("The projector is OFF now. We need to check the screen state");
if (ProjectorPreviousPowerState == "OK1") { // we need to pull up the screen
Serial.println("The projector was powered off, we need to pull up the screen");
ScreenControl(UP); // pull up the screen
delay(PullUpTime); // we need to wait a few seconds while screen will be pulled up
}
else {
Serial.println((String)"Previous projector power state was '" + ProjectorPreviousPowerState + "', nothing to do");
}
ProjectorPreviousPowerState = ProjectorPowerState;
//if projector is OFF, but the trigger is ON, we need to power on the projector
if (voltage > (TriggerHigh*100)) {
Serial.println("Trigger is ON now, so we need to power on the projector too");
Serial1.print("~0000 1\r"); //power on
}
}
else if (ProjectorPowerState == "OK1") {
Serial.println("The projector is ON now. We need to check the screen state");
if (ProjectorPreviousPowerState == "OK0") { // we need to push down the screen
Serial.println("The projector was powered off, we need to push down the screen");
ScreenControl(DOWN); // push down the screen
delay(PushDownTime); // wait for a proper length
ScreenControl(STOP); // and stop
}
else {
Serial.println((String)"Previous projector power state was '" + ProjectorPreviousPowerState + "', nothing to do");
}
ProjectorPreviousPowerState = ProjectorPowerState;
//if projector is ON, but the trigger is OFF
if (voltage < (TriggerLow*100)) {
Serial.println("Trigger is off, so we need to power off the projector too");
Serial1.print("~0000 0\r"); //power off
}
}
else {
Serial.println("The projector state is Unknown. Nothing to do");
}
}
else {
Serial.println("Projector serial connection is not available");
}
//initial request to projector, if it not send anything
Serial1.print("~00124 1\r"); // powerstate query. OK0 if powered down, OK1 if powered on
Serial.println("");
delay(1000);
}
void recvWithEndMarker() { //thanks to https://forum.arduino.cc/t/problem-sending-serial-commands-to-a-video-projector/481406/4
static byte ndx = 0;
char endMarker = '\r';
char rc;
while (Serial1.available() > 0 && newData == false) {
rc = Serial1.read();
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
ndx = 0;
newData = true;
}
}
}
void ScreenControl(int Direction) {
digitalWrite(EN,LOW); // Activate the multiplexer
switch (Direction) {
case 0: // multiplexer channel C0
Serial.println("Mode: STOP");
digitalWrite(S0,LOW);
digitalWrite(S1,LOW);
digitalWrite(S2,LOW);
digitalWrite(S3,LOW);
break;
case 1: // multiplexer channel C1
Serial.println("Mode: DOWN");
digitalWrite(S0,HIGH);
digitalWrite(S1,LOW);
digitalWrite(S2,LOW);
digitalWrite(S3,LOW);
break;
case 2: // multiplexer channel C2
Serial.println("Mode: UP");
digitalWrite(S0,LOW);
digitalWrite(S1,HIGH);
digitalWrite(S2,LOW);
digitalWrite(S3,LOW);
break;
}
delay(100);
digitalWrite(EN, HIGH); //reset the multiplexer
}
void loop() {
}
#include <linux/uinput.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <android/log.h>
#include <jni.h>
int uinput;
extern "C"
JNIEXPORT void JNICALL
Java_com_monobogdan_inputservicebridge_InputNative_init(JNIEnv *env, jclass clazz) {
uinput = open("/dev/input/event2", O_WRONLY);
__android_log_print(ANDROID_LOG_DEBUG , "Test", uinput >= 0 ? "Open event OK" : "Failed to open event");
}
void emit(int fd, int type, int code, int val)
{
struct input_event ie;
ie.type = type;
ie.code = code;
ie.value = val;
/* timestamp values below are ignored */
ie.time.tv_sec = 0;
ie.time.tv_usec = 0;
write(fd, &ie, sizeof(ie));
}
extern "C"
JNIEXPORT void JNICALL
Java_com_monobogdan_inputservicebridge_InputNative_sendKeyEvent(JNIEnv *env, jclass clazz,
jint key_code, jboolean pressed) {
__android_log_print(ANDROID_LOG_DEBUG , "Test", "Send");
emit(uinput, EV_KEY, key_code, (bool)pressed ? 1 : 0);
emit(uinput, EV_SYN, SYN_REPORT, 0);
}package com.monobogdan.inputservicebridge;
public class InputListener extends Service {
private static final int tty = 3;
private InputManager iManager;
private Map<Character, Integer> keyMap;
private Method injectMethod;
private Process runAsRoot(String cmd)
{
try {
return Runtime.getRuntime().exec(new String[] { "su", "-c", cmd });
}
catch (IOException e)
{
e.printStackTrace();
return null;
}
}
@Override
public void onCreate() {
super.onCreate();
// According to linux key map (input-event-codes.h)
keyMap = new HashMap<>();
keyMap.put('U', 103);
keyMap.put('D', 108);
keyMap.put('L', 105);
keyMap.put('R', 106);
keyMap.put('E', 115);
keyMap.put('B', 158);
keyMap.put('A', 232);
keyMap.put('C', 212);
InputNative.init();
try {
runAsRoot("chmod 777 /dev/input/event2").waitFor();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
Process proc = runAsRoot("cat /dev/ttyMT" + tty);
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
while(true)
{
try {
String line = reader.readLine();
if(line != null && line.length() > 0) {
Log.i("Hi", "run: " + line);
boolean pressing = line.charAt(0) == 'D';
int keyCode = keyMap.get(line.charAt(2));
Log.i("TAG", "run: " + keyCode);
InputNative.sendKeyEvent(keyCode, pressing);
}
}
catch(IOException e)
{
e.printStackTrace();
}
/*try {
Thread.sleep(1000 / 30);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
}
}
});
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pico/stdlib.h"
#include "pico/time.h"
#include "hardware/uart.h"
struct keyMap
{
int gpio;
char key;
bool pressed;
int lastTick;
};
keyMap keys[] = {
{
15,
'L',
false,
0
},
{
14,
'U',
false,
0
},
{
13,
'D',
false,
0
},
{
12,
'R',
false,
0
},
{
11,
'E',
false,
0
},
{
10,
'B',
false,
0
},
{
20,
'A',
false,
0
},
{
21,
'C',
false,
0
}
};
#define KEY_NUM 8
int main() {
stdio_init_all();
uart_init(uart0, 921600);
gpio_set_function(PICO_DEFAULT_UART_TX_PIN, GPIO_FUNC_UART);
gpio_set_function(PICO_DEFAULT_UART_RX_PIN, GPIO_FUNC_UART);
sleep_ms(1000); // Allow serial monitor to settle
for(int i = 0; i < KEY_NUM; i++)
{
gpio_init(keys[i].gpio);
gpio_set_dir(keys[i].gpio, false);
gpio_pull_up(keys[i].gpio);
}
while(true)
{
int now = time_us_32();
for(int i = 0; i < KEY_NUM; i++)
{
char buf[5];
buf[1] = ' ';
buf[3] = '\n';
buf[4] = 0;
if(!gpio_get(keys[i].gpio) && !keys[i].pressed && now - keys[i].lastTick > 15500)
{
buf[0] = 'D';
buf[2] = keys[i].key;
puts(buf);
keys[i].lastTick = now;
keys[i].pressed = true;
continue;
}
if(gpio_get(keys[i].gpio) && keys[i].pressed && now - keys[i].lastTick > 15500)
{
buf[0] = 'U';
buf[2] = keys[i].key;
puts(buf);
keys[i].pressed = false;
keys[i].lastTick = now;
}
Comments