I'm making a Snake game using ANSI escape codes in C++. I want to get the keyboard input and, for example, when I press W then the snake will move up and the direction will be set to U so it will keep moving up until I press another direction key:
void Map::getSnakeMovement(char *path) { ifstream keyboardFile(path, ios::in | ios::binary);
keyboardInput kbInput;
if (!keyboardFile) {
cerr << "Cannot read the keyboard input" << endl;
return;
}
while(1) {
keyboardFile.read((char*)&kbInput, sizeof(keyboardInput));
switch(this->currentDirection) {
case 'L':
this->snake[0].move(this->snake[0].getXPosition() - 1, this->snake[0].getYPosition());
this->isPoint(this->snake[0].getXPosition(), this->snake[0].getYPosition());
this->scoreboard.display();
break;
case 'U':
this->snake[0].move(this->snake[0].getXPosition(), this->snake[0].getYPosition() - 1);
this->isPoint(this->snake[0].getXPosition(), this->snake[0].getYPosition());
this->scoreboard.display();
break;
case 'R':
this->snake[0].move(this->snake[0].getXPosition() + 1, this->snake[0].getYPosition());
this->isPoint(this->snake[0].getXPosition(), this->snake[0].getYPosition());
this->scoreboard.display();
break;
case 'D':
this->snake[0].move(this->snake[0].getXPosition(), this->snake[0].getYPosition() + 1);
this->isPoint(this->snake[0].getXPosition(), this->snake[0].getYPosition());
this->scoreboard.display();
break;
}
if (kbInput.type == 1 && kbInput.value == 1 && kbInput.code != 0) {
switch(kbInput.code) {
case W_KEY:
this->currentDirection = 'U';
break;
case A_KEY:
this->currentDirection = 'L';
break;
case S_KEY:
this->currentDirection = 'D';
break;
case D_KEY:
this->currentDirection = 'R';
break;
}
}
Utils::moveCursor(this->height + 20, 1);
}
keyboardFile.close();
}
But the result is not as expected. Is the read method blocking the flow?
I have written below function and check it using Arduino MEGA. This code is simply read PORTC and filter it's 4bit and according to that bit values, function returns -2 to 13.
#define PDL_1_BRN 37 //PC0
#define PDL_2_GRN 36 //PC1
#define PDL_3_WHT 35 //PC2
#define PDL_4_YEL 34 //PC3
void setup() {
Serial.begin(9600);
pinMode(PDL_1_BRN, INPUT); //use external pullup
pinMode(PDL_2_GRN, INPUT);
pinMode(PDL_3_WHT, INPUT);
pinMode(PDL_4_YEL, INPUT);
}
uint32_t t = 0;
void loop() {
t = micros();
getPedalState();
Serial.println(micros() - t);
}
int8_t getPedalState() {
uint8_t val = 0;
val = PINC & 0x0F;
switch (val) {
case 0x0F:
return 0;
break;
case 0x0B:
return 1;
break;
case 0x09:
return 2;
break;
case 0x01:
return 3;
break;
case 0x05:
return 4;
break;
case 0x0D:
return 5;
break;
case 0x0C:
return 6;
break;
case 0x04:
return 7;
break;
case 0x00:
return 8;
break;
case 0x08:
return 9;
break;
case 0x0A:
return 10;
break;
case 0x02:
return 11;
break;
case 0x06:
return 12;
break;
case 0x0E:
return 13;
break;
case 0x07:
return -1;
break;
case 0x03:
return -2;
break;
}
}
Using separate code I measured PORTC read execution time using micros(). It takes 4uS as I measured.
This code also read the PORTC and then used a switch case to identify port value.
But, this entire function also gets only 4uS to execute all instructions (port reading, masking, switch case).
That means, switch case didn't take at least 1uS to execute.
As I know, swich case start to compare one by one top of the code to bottom of the code. (That means switch case gets more time to return value in bottom of the code.) But, this code gets only 4uS for any value of the PORTC.
Please explain how switch case works in Arduino/C++.
The resolution of the micros function is 4uS. That's why you're seeing the same values. Toggle a pin instead and watch it with an oscilloscope and you'll get a better idea of the actual timing.
I'm writing a programm that's using getch() to scan for arrow keys. My code so far is:
switch(getch()) {
case 65: // key up
break;
case 66: // key down
break;
case 67: // key right
break;
case 68: // key left
break;
}
Problem is that when I press 'A', 'B', 'C' or 'D' the code will also executed, because 65 is the decimal code for 'A', etc...
Is there a way to check for an arrow key without call others?
Thanks!
By pressing one arrow key getch will push three values into the buffer:
'\033'
'['
'A', 'B', 'C' or 'D'
So the code will be something like this:
if (getch() == '\033') { // if the first value is esc
getch(); // skip the [
switch(getch()) { // the real value
case 'A':
// code for arrow up
break;
case 'B':
// code for arrow down
break;
case 'C':
// code for arrow right
break;
case 'D':
// code for arrow left
break;
}
}
getch () function returns two keycodes for arrow keys (and some other special keys), as mentioned in the comment by FatalError. It returns either 0 (0x00) or 224 (0xE0) first, and then returns a code identifying the key that was pressed.
For the arrow keys, it returns 224 first followed by 72 (up), 80 (down), 75 (left) and 77 (right). If the num-pad arrow keys (with NumLock off) are pressed, getch () returns 0 first instead of 224.
Please note that getch () is not standardized in any way, and these codes might vary from compiler to compiler. These codes are returned by MinGW and Visual C++ on Windows.
A handy program to see the action of getch () for various keys is:
#include <stdio.h>
#include <conio.h>
int main ()
{
int ch;
while ((ch = _getch()) != 27) /* 27 = Esc key */
{
printf("%d", ch);
if (ch == 0 || ch == 224)
printf (", %d", _getch ());
printf("\n");
}
printf("ESC %d\n", ch);
return (0);
}
This works for MinGW and Visual C++. These compilers use the name _getch () instead of getch () to indicate that it is a non-standard function.
So, you may do something like:
ch = _getch ();
if (ch == 0 || ch == 224)
{
switch (_getch ())
{
case 72:
/* Code for up arrow handling */
break;
case 80:
/* Code for down arrow handling */
break;
/* ... etc ... */
}
}
So, after alot of struggle, I miraculously solved this everannoying issue !
I was trying to mimic a linux terminal and got stuck at the part where it keeps a command history which can be accessed by pressing up or down arrow keys. I found ncurses lib to be painfuly hard to comprehend and slow to learn.
char ch = 0, k = 0;
while(1)
{
ch = getch();
if(ch == 27) // if ch is the escape sequence with num code 27, k turns 1 to signal the next
k = 1;
if(ch == 91 && k == 1) // if the previous char was 27, and the current 91, k turns 2 for further use
k = 2;
if(ch == 65 && k == 2) // finally, if the last char of the sequence matches, you've got a key !
printf("You pressed the up arrow key !!\n");
if(ch == 66 && k == 2)
printf("You pressed the down arrow key !!\n");
if(ch != 27 && ch != 91) // if ch isn't either of the two, the key pressed isn't up/down so reset k
k = 0;
printf("%c - %d", ch, ch); // prints out the char and it's int code
It's kind of bold but it explains alot. Good luck !
The keypad will allow the keyboard of the user's terminal to allow for function keys to be interpreted as a single value (i.e. no escape sequence).
As stated in the man page:
The keypad option enables the keypad of the user's terminal. If
enabled (bf is TRUE), the user can press a function key (such as an
arrow key) and wgetch returns a single value representing the function
key, as in KEY_LEFT. If disabled (bf is FALSE), curses does not treat
function keys specially and the program has to interpret the escape
sequences itself. If the keypad in the terminal can be turned on (made
to transmit) and off (made to work locally), turning on this option
causes the terminal keypad to be turned on when wgetch is called. The
default value for keypad is false.
Actually, to read arrow keys one need to read its scan code.
Following are the scan code generated by arrow keys press (not key release)
When num Lock is off
Left E0 4B
Right E0 4D
Up E0 48
Down E0 50
When Num Lock is on these keys get preceded with E0 2A
Byte E0 is -32
Byte 48 is 72 UP
Byte 50 is 80 DOWN
user_var=getch();
if(user_var == -32)
{
user_var=getch();
switch(user_var)
{
case 72:
cur_sel--;
if (cur_sel==0)
cur_sel=4;
break;
case 80:
cur_sel++;
if(cur_sel==5)
cur_sel=1;
break;
}
}
In the above code I have assumed programmer wants to move 4 lines only.
how about trying this?
void CheckKey(void) {
int key;
if (kbhit()) {
key=getch();
if (key == 224) {
do {
key=getch();
} while(key==224);
switch (key) {
case 72:
printf("up");
break;
case 75:
printf("left");
break;
case 77:
printf("right");
break;
case 80:
printf("down");
break;
}
}
printf("%d\n",key);
}
int main() {
while (1) {
if (kbhit()) {
CheckKey();
}
}
}
(if you can't understand why there is 224, then try running this code: )
#include <stdio.h>
#include <conio.h>
int main() {
while (1) {
if (kbhit()) {
printf("%d\n",getch());
}
}
}
but I don't know why it's 224. can you write down a comment if you know why?
for a solution that uses ncurses with working code and initialization of ncurses see getchar() returns the same value (27) for up and down arrow keys
I have written a function using getch to get arrow code. it's a quick'n'dirty solution but the function will return an ASCII code depending on arrow key :
UP : -10
DOWN : -11
RIGHT : -12
LEFT : -13
Moreover,with this function, you will be able to differenciate the ESCAPE touch and the arrow keys. But you have to press ESC 2 time to activate the ESC key.
here the code :
char getch_hotkey_upgrade(void)
{
char ch = 0,ch_test[3] = {0,0,0};
ch_test[0]=getch();
if(ch_test[0] == 27)
{
ch_test[1]=getch();
if (ch_test[1]== 91)
{
ch_test[2]=getch();
switch(ch_test[2])
{
case 'A':
//printf("You pressed the up arrow key !!\n");
//ch = -10;
ch = -10;
break;
case 'B':
//printf("You pressed the down arrow key !!\n");
ch = -11;
break;
case 'C':
//printf("You pressed the right arrow key !!\n");
ch = -12;
break;
case 'D':
//printf("You pressed the left arrow key !!\n");
ch = -13;
break;
}
}
else
ch = ch_test [1];
}
else
ch = ch_test [0];
return ch;
}
I'm Just a starter, but i'v created a char(for example "b"), and I do b = _getch(); (its a conio.h library's command)
And check
If (b == -32)
b = _getch();
And do check for the keys (72 up, 80 down, 77 right, 75 left)
void input_from_key_board(int &ri, int &ci)
{
char ch = 'x';
if (_kbhit())
{
ch = _getch();
if (ch == -32)
{
ch = _getch();
switch (ch)
{
case 72: { ri--; break; }
case 80: { ri++; break; }
case 77: { ci++; break; }
case 75: { ci--; break; }
}
}
else if (ch == '\r'){ gotoRowCol(ri++, ci -= ci); }
else if (ch == '\t'){ gotoRowCol(ri, ci += 5); }
else if (ch == 27) { system("ipconfig"); }
else if (ch == 8){ cout << " "; gotoRowCol(ri, --ci); if (ci <= 0)gotoRowCol(ri--, ci); }
else { cout << ch; gotoRowCol(ri, ci++); }
gotoRowCol(ri, ci);
}
}
Try this...
I am in Windows 7 with Code::Blocks
while (true)
{
char input;
input = getch();
switch(input)
{
case -32: //This value is returned by all arrow key. So, we don't want to do something.
break;
case 72:
printf("up");
break;
case 75:
printf("left");
break;
case 77:
printf("right");
break;
case 80:
printf("down");
break;
default:
printf("INVALID INPUT!");
break;
}
}
for using arrow keys, first it has to be stored for analyzing it. That's why I am using scanf to store it.
But when I try to run this code, and when I press up key, then it is showing ^[[A and when I press enter then this ^[[A removes and program exit without printing printf statement of printf("%s",c). and printf("UP\n").
#include <stdio.h>
int main()
{
char c[50];
scanf("%s",&c);
printf("%s",c);
if (getch() == '\033'){ // if the first value is esc
getch();// skip the [
getch();// skip the [
switch(getch()) { // the real value
case 'A':
printf("UP\n");
break;
case 'B':
printf("DOWN\n");
break;
}
}
return 0;
}
You will find it easy if you use the ncurses library. Just go through the documentation to see how to install it.
After installing read the part on Interfacing with the key board
Here is a sample code
#include <ncurses.h>
int main()
{
int ch;
initscr();
raw();
keypad(stdscr, TRUE);
noecho();
while(1)
{
ch = getch();
switch(ch)
{
case KEY_UP:
printw("\nUp Arrow");
break;
case KEY_DOWN:
printw("\nDown Arrow");
break;
case KEY_LEFT:
printw("\nLeft Arrow");
break;
case KEY_RIGHT:
printw("\nRight Arrow");
break;
}
if(ch == KEY_UP)
break;
}
endwin();
}
I'm learning PIC (pic18f4550) and pretty new to microcontroller programming. I'm trying get value of three button on PORTA and send it to a 8x8 led matrix as X coordinates through a 74LS595. The problem is that the value go to the led matrix doesnt change when i pressed the buttons to create different value. I'm simulating on Proteus so I guess I don't need debounce function.
Here's my code and schematic:
#include<p18f4550.h>
#define SCK LATBbits.LATB0
#define DATA PORTBbits.RB1
#define SCL PORTBbits.RB2
void Data_in(unsigned char k){
DATA=k;
SCK=0;
SCK=1;
}
void LatchData(){
SCL=0;
SCL=1;
}
void Send1byte(unsigned char data)
{
unsigned char i,temp;
for(i=0;i<8;i++)
{
temp = data & (1<<i);
if(temp)
{
DATA = 1;
}
else
{
DATA = 0;
}
SCK = 0;
SCK = 1;
}
SCL = 0;
SCL = 1;
}
unsigned char getMatrixX(unsigned char in_X)
{
switch(in_X)
{
case 0: // the value stuck here
return 0b01111111;
case 1:
return 0b10111111;
case 2:
return 0b11011111;
case 3:
return 0b11101111;
case 4:
return 0b11110111;
case 5:
return 0b11111011;
case 6:
return 0b11111101;
case 7:
return 0b11111110;
default:
return 0b11111111;
}
}
void main()
{
TRISA = 1;
TRISC = 1;
TRISB = 0;
TRISD = 0;
PORTD = 0x80;
while(1){
Send1byte(getMatrixX(LATA));
}
}
This is link to my schematic:
my schematic
Really appreciate any solutions and advices. Sorry for my bad english.
the analogue function of RA0:RA3 is the real problem here, so adding these will fix:
ADCON1 = 0x0F; // All digital inputs
CMCON = 0x07; // Comparators off (note this is the POR default)
Thanks David in this question: https://electronics.stackexchange.com/questions/111614/pic-programming-get-value-of-multiple-buttons-to-a-port/111625?noredirect=1#111625 , he explained it very well.