/*
AutoType Keyboard for the Raspberry PICO
NOTE: WOKWI sketch uses the serial port instead of Keyboard.
PICO pins:-
USB
(GP0)(GP1)[GND](GP2)(GP3)(GP4)(GP5)[GND](GP6)(GP7)(GP8)(GP9)[GND](GP10)(GP11)(GP12)(GP13)[GND](GP14)(GP15)
Use links / slide switches to select a feature
GP2 - SEND \N - send ENTER, it de-focused the input area, so allow it to be disabled.
GP6 - SLOW - strap low for faster typing
GP9 - HALT - The Pico can be reprogrammed using BOOTSEL, so this is not essential
GP10 - TYPING_IDLE - assert low when typing, Only start typing if high.
Overview:-
I needed to automate typing a conversation, between two people over an App like a Chat Bot session.
The App needed a slow stream of repeatable text to soak test it and fill up scroll buffers, over many minutes.
It needed a trickle of characters as if typed on the App's keyboard(s).
I can plug in an external keyboard at each end.
The Arduino IDE has Keyboard examples.
Raspberry PICO were available from Farnell for about 6 GBP.
There are examples using them as USB Keyboards.
It is impractical to read the display, but a wire can be used between two of these devices, so they can type in turn.
Typically, Person A: types to Person B: and B: types back.
Raspberry PICO were available from Farnell for about 6 GBP.
There are examples using them as USB Keyboards.
See: http://ccgi.dougrice.plus.com/cgi-bin/wiki.pl?AutoType
It is easy to get the Arduino IDE to work.
https://www.arduino.cc/
https://www.arduino.cc/reference/en/language/functions/usb/keyboard/
https://www.arduino.cc/en/Tutorial/BuiltInExamples/KeyboardMessage
Add Arduino "MBED OS RP2040 boards"
Based on Keyboard example
With "Arduino MBED OS RP2040 Boards 3.3.0" installed you can generate .uf2 files for upload to the PICO
https://github.com/arduino/ArduinoCore-mbed
https://github.com/arduino/ArduinoCore-mbed/tree/master/libraries/USBHID/examples
Example:
#include "PluggableUSBHID.h"
#include "USBKeyboard.h"
USBKeyboard Keyboard;
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
delay(1000);
Keyboard.printf("Hello world\n\r");
}
========================================================
SEC: 1.0 - Design Brainstorm and thoughts:-
========================================================
I needed to automate typing a conversation, between two people over an App like a Chat Bot session.
The App needed a slow stream of repeatable text to soak test it and fill up scroll buffers, over many minutes.
It needed a trickle of characters as if typed on the App's keyboard(s).
I can plug an external keyboard at each end, which could be two of these PICOs. This is not essential.
It is impracticle to read the display, but a wire can be used between two of these devices, so they can type in turn.
Typically, Person A: types to Person B: and B: types back.
timeline:-
A: | typing |GA| waiting | typing |GA| waiting | typing
B: | waiting | typing |GA| waiting | typing |GA| waiting
A: types pressing keys on a keyboard, at up to 10 characters a second or slower
A: hands over to B: by sending "GA" to Go Ahead, then waits
B: reads the typing and can type but should wait until A: stops typing, before starting.
B: types and A: waits til B: stops.
Typing on a smart phone soft keyboard is slower.
some devices display both conversations in a single line of text, making it difficult to read.
Use a one PIN Wired Or BUS wire to communicate between two of these PICOs.
Assert Low when Typing,
Stop typing when "\n" found - Users send GA for Go Ahead
Wait for it to go high, before sarting to type.
pull up
|
-----+-----+-----+----------+--- Wired OR buss - Assert low when typing.
| | |
[ A ] [ B ] [ SW ]
[ A ] and [ B ] Wait for high to start typing and assert a low
[SW] is a switch which can pull low to inhibit typing.
on start up hold off typing.
When waiting look for ----____ before starting typing.
*/
/*========================================================
SEC: 1.0 - Configuration
======================================================*/
#define TYPING_INTER_KEY_DELAY 20
//
// there was a bug with the SmartPhone App
// Pressing ENTER looses focus, so suppress ENTER
// select if "\n" presses ENTER key
//
#define nNOENTER true
#define NOENTER false
/*
This code can use a Raspberry PICO or RP2
Arduino IDE Tools configuration
RP2 PICO
Board: Raspberry Pi Pico
Programmer: N/A - ensure bootsel button is pressed when you plug in PICO
*/
/*
#include "PluggableUSBHID.h"
#include "USBKeyboard.h"
USBKeyboard Keyboard;
*/
#define HALT 9
#define TYPING 10
/*
PICO pins:-
USB
(GP0)(GP1)[GND](GP2)(GP3)(GP4)(GP5)[GND](GP6)(GP7)(GP8)(GP9)[GND](GP10)(GP11)(GP12)(GP13)[GND](GP14)(GP15)
*/
/* Use links to select a feature
GP2 - SEND \N - send ENTER, it de-focused the input area, so allow it to be disabled.
GP6 - SLOW - strap low for faster typing
GP9 - HALT - The Pico can be reprogrammed using BOOTSEL, so this is not essential
GP10 - TYPING_IDLE - assert low when typing
*/
/*
*/
/*
This is BeeTea Engineer, DHR, making a test call.
Please hang up the B-leg
I am testing the new Relay UK app
Hello Doug here
Can you see my typing? The Quick brown fox jumps over the lazy dog I am testing the new Relay UK app
ts: 107 seconds This is BeeTea Engineer, DHR, making a test call.
Please hang up the B-leg
I am testing the new Relay UK app
Hello Doug here
*/
/*========================================================
SEC: 2.0 - Typing Text
======================================================*/
#define PHONE
/* Phone User typing - The \n indicate end of sentence.*/
#ifdef PHONE
int phone = true;
// send space followed by a space.
// The phone looses focus when the ENTER key is pressed.
// It buffers text and waits for a pause. send some single spaces or double spaces.
// A user could send GA to hand over to the other End
// A \n is used to signal end of typing.
char myString[] = " This is BeeTea Engineer, DHR, making a test call.\n "
" Please hang up the B-leg \n "
" I am testing the new Relay UK app \n "
" Hello Doug here \n "
" Can you see my typing? \n "
" The Quick brown fox jumps over the lazy dog \n "
" I am testing the new Relay UK app \n "
//" 1 2 3 4 5 6 7 8 9 ! £ $ % ^ & * ( ) _- + = { } [ ] ~ # : ; @ ' < > , . / ?"
;
#else
int phone = false;
/* Agent typing - The \n indicate end of sentence. */
char myString[] = " Welcome to Chit Chat UK \n "
" Please type your name? \n "
" You are talking to Jack \n "
" How May I help you today \n "
" Okay I will type back? \n "
" The Quick brown fox jumps over the lazy dog \n "
" Hello Caller the other party has cleared. \n "
" \n ";
#endif
/*========================================================
SEC: 3.0 - Variables
======================================================*/
int slowSpeed = true;
int waiting = true;
// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastTs = 0; // the last timestamp
char * ptr;
/*========================================================
SEC: 4.0 - Functions
======================================================*/
void setup() {
Serial1.begin(9600);
// don't need to set anything up to use DigiKeyboard
ptr = myString;
pinMode( 2, INPUT_PULLUP );
pinMode( 6, INPUT_PULLUP );
//pinMode( 9, INPUT_PULLUP );
//pinMode( 10, INPUT_PULLUP );
pinMode( HALT, INPUT_PULLUP );
pinMode( TYPING, INPUT_PULLUP ); // used for WiredOR
pinMode( LED_BUILTIN, OUTPUT );
waiting = true;
Serial1.println(" hello , Use slide switches to select features\n");
Serial1.println(" use CRLRF, speed, typing\n");
}
void polledTimeSlice() {
unsigned long now = millis(); // the last timestamp
// using unsigned so be caureful.
if ( now - lastTs > 300 ) {
// 0.1 second tick
lastTs = now;
//
// payload - run every 300 ticks.
//
// if typing TYPING asserted Low, wait for it to go high
// If input goes low turn off waiting
//if ( ! digitalRead( IP ) ){
if ( digitalRead( TYPING ) ) {
waiting = false;
}
}
}
void LED( int on ) {
/* IF on == TRUE then Typing. Assest TYPING LOW using Wired OR */
if ( on ) {
// ASSERT LOW
pinMode( LED_BUILTIN, OUTPUT );
pinMode( TYPING, OUTPUT );
// Wired OR
digitalWrite( LED_BUILTIN, on );
digitalWrite( TYPING, LOW );
} else {
pinMode( LED_BUILTIN, OUTPUT );
// to turn on a PULLUP make pin input
pinMode( TYPING, INPUT_PULLUP );
digitalWrite( LED_BUILTIN, on );
}
}
/*========================================================
SEC: 5.0 - Functions - delay
======================================================*/
void delay_( unsigned long ms ) {
delay( ms );
}
void wait() {
// pick a random delay and square it to make it more like real typing?
//delay(random( 0, TYPING_INTER_KEY_DELAY )*random( 0, TYPING_INTER_KEY_DELAY ));
if ( digitalRead( 6 ) == 1 ) {
delay( random( 50, 250 ) );
} else {
delay( random( 0, 100 ) );
}
}
void waitLong() {
int count;
delay( random( 1000, 2000 ) );
}
/*========================================================
SEC: 6.0 - Functions Increment & Type Key
======================================================*/
void incStringPtr() {
unsigned long ts = 0;
/* end of string return to start.*/
ptr ++ ;
// if space end of word.
if ( ptr[0] == ' ') {
}
// END OF LOOP
if ( ptr[0] == '\0') {
ptr = myString;
if ( slowSpeed ) {
slowSpeed = false;
} else {
slowSpeed = true;
}
ts = millis();
/*
Keyboard.printf( "%s", " ts: " );
Keyboard.printf( "%d", ts / 1000 );
Keyboard.printf( "%s", " seconds " );
*/
}
}
void typeKey( char letter ) {
// enable typing in HALT is high in this version.
if ( digitalRead( HALT ) ) {
// this is generally not necessary but with some older systems it seems to
// prevent missing the first character after a delay:
// DigiKeyboard.sendKeyStroke(0);
// if ( NOENTER && isControl( letter ) ) {
// Read GP2 to select sending \n
if ( isControl( letter ) && digitalRead( 2 ) ) {
letter = ' ';
}
//Keyboard.printf( "%c", letter );
Serial1.print( letter );
incStringPtr();
}
}
/*
*/
/*========================================================
SEC: 7.0 - Functions Main Loop
======================================================*/
void loop() {
delay(1);
polledTimeSlice();
/* work through string and print character by character */
/* check if input low and enable typing. */
if ( waiting ) {
return;
}
// look for end of sentence,
if ( isControl( ptr[0] ) ) {
// turn off LED at end of sentence
// This is used to tell other end as well.
LED( LOW );
// end of sentence turn os Waiting flag
// so loop waits for other end to finish sentence.
waiting = true;
typeKey( ptr[0] );
wait();
} else {
LED( HIGH );
/* type character */
typeKey( ptr[0] );
if ( slowSpeed ) {
wait();
}
wait();
}
if ( isWhitespace( ptr[0] ) ) {
wait();
}
}
/*========================================================
SEC: 8.0 - Examples
======================================================*/
/*
This is BeeTea Engineer, DHR, making a test call.
Please hang up the B-leg
I am testing the new Relay UK app
Hello Doug here
Can you see my typing?
The Quick brown fox jumps over the lazy dog
I am testing the new Relay UK app
ts: 60 seconds This is BeeTea Engineer, DHR, making a test call.
Please hang up the B-leg
I am testing the new Relay UK app
Hello Doug here
*/
/*========================================================
SEC: 9.0 - End
======================================================*/