2021-03-20 22:39:00 +08:00
|
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2006-2021, RT-Thread Development Team
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
*
|
|
|
|
|
* Change Logs:
|
|
|
|
|
* Date Author Notes
|
|
|
|
|
*/
|
2015-09-30 16:26:40 +08:00
|
|
|
|
|
2021-03-20 22:39:00 +08:00
|
|
|
|
#include <stdio.h>
|
2015-09-30 16:26:40 +08:00
|
|
|
|
#include <rthw.h>
|
|
|
|
|
#include <rtdevice.h>
|
|
|
|
|
#include <rtthread.h>
|
|
|
|
|
#include <rtdevice.h>
|
|
|
|
|
|
|
|
|
|
/* uart driver */
|
|
|
|
|
struct console_uart
|
|
|
|
|
{
|
|
|
|
|
int rx_ready;
|
|
|
|
|
|
|
|
|
|
struct rt_ringbuffer rb;
|
|
|
|
|
rt_uint8_t rx_buffer[256];
|
|
|
|
|
} _console_uart;
|
|
|
|
|
static struct rt_serial_device _serial;
|
|
|
|
|
|
|
|
|
|
#define SAVEKEY(key) do { char ch = key; rt_ringbuffer_put_force(&(_console_uart.rb), &ch, 1); } while (0)
|
2013-01-22 16:57:47 +08:00
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
2013-01-08 22:40:58 +08:00
|
|
|
|
#include <windows.h>
|
|
|
|
|
#include <mmsystem.h>
|
|
|
|
|
#include <conio.h>
|
2022-05-17 14:19:53 +08:00
|
|
|
|
extern int getch(void);
|
2013-01-08 22:40:58 +08:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Handler for OSKey Thread
|
|
|
|
|
*/
|
|
|
|
|
static HANDLE OSKey_Thread;
|
|
|
|
|
static DWORD OSKey_ThreadID;
|
|
|
|
|
|
|
|
|
|
static DWORD WINAPI ThreadforKeyGet(LPVOID lpParam);
|
2015-09-30 16:26:40 +08:00
|
|
|
|
void console_lowlevel_init(void)
|
2013-01-08 22:40:58 +08:00
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* create serial thread that receive key input from keyboard
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
OSKey_Thread = CreateThread(NULL,
|
|
|
|
|
0,
|
|
|
|
|
(LPTHREAD_START_ROUTINE)ThreadforKeyGet,
|
|
|
|
|
0,
|
|
|
|
|
CREATE_SUSPENDED,
|
|
|
|
|
&OSKey_ThreadID);
|
|
|
|
|
if (OSKey_Thread == NULL)
|
|
|
|
|
{
|
|
|
|
|
//Display Error Message
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-09-30 16:26:40 +08:00
|
|
|
|
|
2013-01-08 22:40:58 +08:00
|
|
|
|
SetThreadPriority(OSKey_Thread,
|
|
|
|
|
THREAD_PRIORITY_NORMAL);
|
|
|
|
|
SetThreadPriorityBoost(OSKey_Thread,
|
|
|
|
|
TRUE);
|
|
|
|
|
SetThreadAffinityMask(OSKey_Thread,
|
|
|
|
|
0x01);
|
|
|
|
|
/*
|
|
|
|
|
* Start OS get key Thread
|
|
|
|
|
*/
|
|
|
|
|
ResumeThread(OSKey_Thread);
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-30 16:26:40 +08:00
|
|
|
|
static DWORD WINAPI ThreadforKeyGet(LPVOID lpParam)
|
2013-01-22 16:57:47 +08:00
|
|
|
|
#else /* POSIX version */
|
|
|
|
|
|
|
|
|
|
#include <pthread.h>
|
|
|
|
|
#include <semaphore.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#include <termios.h> /* for tcxxxattr, ECHO, etc */
|
|
|
|
|
#include <unistd.h> /* for STDIN_FILENO */
|
|
|
|
|
|
|
|
|
|
static void * ThreadforKeyGet(void * lpParam);
|
|
|
|
|
static pthread_t OSKey_Thread;
|
2015-09-30 16:26:40 +08:00
|
|
|
|
|
|
|
|
|
void console_lowlevel_init(void)
|
2013-01-22 16:57:47 +08:00
|
|
|
|
{
|
|
|
|
|
int res;
|
2013-07-22 23:02:03 +08:00
|
|
|
|
|
2013-01-22 16:57:47 +08:00
|
|
|
|
res = pthread_create(&OSKey_Thread, NULL, &ThreadforKeyGet, NULL);
|
|
|
|
|
if (res)
|
|
|
|
|
{
|
|
|
|
|
printf("pthread create faild, <%d>\n", res);
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct termios oldt, newt;
|
|
|
|
|
/*simulate windows' getch(), it works!!*/
|
2015-09-30 16:26:40 +08:00
|
|
|
|
static void set_stty(void)
|
2013-01-22 16:57:47 +08:00
|
|
|
|
{
|
2021-03-20 22:39:00 +08:00
|
|
|
|
/* get terminal input's attribute */
|
2013-01-22 16:57:47 +08:00
|
|
|
|
tcgetattr(STDIN_FILENO, &oldt);
|
|
|
|
|
newt = oldt;
|
|
|
|
|
|
2021-03-20 22:39:00 +08:00
|
|
|
|
/* set termios' local mode */
|
2013-01-22 16:57:47 +08:00
|
|
|
|
newt.c_lflag &= ~(ECHO|ICANON);
|
|
|
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-02 08:16:15 +08:00
|
|
|
|
void restore_stty(void)
|
2013-01-22 16:57:47 +08:00
|
|
|
|
{
|
|
|
|
|
/* recover terminal's attribute */
|
|
|
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define getch getchar
|
|
|
|
|
static void * ThreadforKeyGet(void * lpParam)
|
|
|
|
|
#endif /* not _WIN32*/
|
2013-01-08 22:40:58 +08:00
|
|
|
|
{
|
2013-02-07 23:18:59 +08:00
|
|
|
|
/*
|
2015-09-30 18:21:55 +08:00
|
|
|
|
* left key(<EFBFBD><EFBFBD>)<EFBFBD><EFBFBD> 0xe04b
|
|
|
|
|
* up key(<EFBFBD><EFBFBD>)<EFBFBD><EFBFBD> 0xe048
|
|
|
|
|
* right key(<EFBFBD><EFBFBD>)<EFBFBD><EFBFBD> 0xe04d
|
|
|
|
|
* down key(<EFBFBD><EFBFBD>)<EFBFBD><EFBFBD> 0xe050
|
2013-02-07 23:18:59 +08:00
|
|
|
|
*/
|
2013-01-08 22:40:58 +08:00
|
|
|
|
unsigned char key;
|
|
|
|
|
|
2013-01-22 16:57:47 +08:00
|
|
|
|
#ifndef _WIN32
|
|
|
|
|
sigset_t sigmask, oldmask;
|
2021-03-20 22:39:00 +08:00
|
|
|
|
/* set the getchar without buffer */
|
|
|
|
|
sigfillset(&sigmask);
|
|
|
|
|
pthread_sigmask(SIG_BLOCK, &sigmask, &oldmask);
|
|
|
|
|
set_stty();
|
2013-01-22 16:57:47 +08:00
|
|
|
|
#endif
|
2015-09-30 16:26:40 +08:00
|
|
|
|
|
2013-01-08 22:40:58 +08:00
|
|
|
|
(void)lpParam; //prevent compiler warnings
|
2015-09-30 16:26:40 +08:00
|
|
|
|
|
2013-01-08 22:40:58 +08:00
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
key = getch();
|
2013-01-22 16:57:47 +08:00
|
|
|
|
#ifdef _WIN32
|
2013-01-08 22:40:58 +08:00
|
|
|
|
if (key == 0xE0)
|
|
|
|
|
{
|
|
|
|
|
key = getch();
|
|
|
|
|
|
|
|
|
|
if (key == 0x48) //up key , 0x1b 0x5b 0x41
|
|
|
|
|
{
|
2013-02-07 23:18:59 +08:00
|
|
|
|
SAVEKEY(0x1b);
|
|
|
|
|
SAVEKEY(0x5b);
|
|
|
|
|
SAVEKEY(0x41);
|
2013-01-08 22:40:58 +08:00
|
|
|
|
}
|
|
|
|
|
else if (key == 0x50)//0x1b 0x5b 0x42
|
|
|
|
|
{
|
2013-02-07 23:18:59 +08:00
|
|
|
|
SAVEKEY(0x1b);
|
|
|
|
|
SAVEKEY(0x5b);
|
|
|
|
|
SAVEKEY(0x42);
|
2013-01-08 22:40:58 +08:00
|
|
|
|
}
|
2013-10-16 14:54:13 +08:00
|
|
|
|
else if (key == 0x4b)//<- 0x1b 0x5b 0x44
|
|
|
|
|
{
|
|
|
|
|
SAVEKEY(0x1b);
|
|
|
|
|
SAVEKEY(0x5b);
|
|
|
|
|
SAVEKEY(0x44);
|
|
|
|
|
}
|
|
|
|
|
else if (key == 0x4d)//<- 0x1b 0x5b 0x43
|
|
|
|
|
{
|
|
|
|
|
SAVEKEY(0x1b);
|
|
|
|
|
SAVEKEY(0x5b);
|
|
|
|
|
SAVEKEY(0x43);
|
|
|
|
|
}
|
2013-01-08 22:40:58 +08:00
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2013-01-22 16:57:47 +08:00
|
|
|
|
#endif
|
2013-02-07 23:18:59 +08:00
|
|
|
|
SAVEKEY(key);
|
2015-09-30 16:26:40 +08:00
|
|
|
|
|
|
|
|
|
/* Notfiy serial ISR */
|
|
|
|
|
rt_hw_serial_isr(&_serial, RT_SERIAL_EVENT_RX_IND);
|
2013-01-08 22:40:58 +08:00
|
|
|
|
}
|
2013-01-22 16:57:47 +08:00
|
|
|
|
} /*** ThreadforKeyGet ***/
|
2015-09-30 16:26:40 +08:00
|
|
|
|
|
|
|
|
|
static rt_err_t console_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
|
|
|
|
|
{
|
|
|
|
|
/* no baudrate, nothing */
|
|
|
|
|
|
|
|
|
|
return RT_EOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static rt_err_t console_control(struct rt_serial_device *serial, int cmd, void *arg)
|
|
|
|
|
{
|
|
|
|
|
struct console_uart* uart;
|
|
|
|
|
|
|
|
|
|
RT_ASSERT(serial != RT_NULL);
|
|
|
|
|
uart = (struct console_uart *)serial->parent.user_data;
|
|
|
|
|
|
|
|
|
|
switch (cmd)
|
|
|
|
|
{
|
|
|
|
|
case RT_DEVICE_CTRL_CLR_INT:
|
|
|
|
|
uart->rx_ready = 0;
|
|
|
|
|
break;
|
|
|
|
|
case RT_DEVICE_CTRL_SET_INT:
|
|
|
|
|
uart->rx_ready = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return RT_EOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int console_putc(struct rt_serial_device *serial, char c)
|
|
|
|
|
{
|
|
|
|
|
int level;
|
|
|
|
|
struct console_uart* uart;
|
|
|
|
|
|
|
|
|
|
RT_ASSERT(serial != RT_NULL);
|
|
|
|
|
uart = (struct console_uart *)serial->parent.user_data;
|
|
|
|
|
|
|
|
|
|
#if 0 /* Enable it if you want to save the console log */
|
|
|
|
|
{
|
|
|
|
|
static FILE* fp = NULL;
|
|
|
|
|
|
|
|
|
|
if (fp == NULL)
|
|
|
|
|
fp = fopen("log.txt", "wb+");
|
|
|
|
|
|
|
|
|
|
if (fp != NULL)
|
|
|
|
|
fwrite(buffer, size, 1, fp);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
level = rt_hw_interrupt_disable();
|
|
|
|
|
fwrite(&c, 1, 1, stdout);
|
2021-03-20 22:39:00 +08:00
|
|
|
|
fflush(stdout);
|
2015-09-30 16:26:40 +08:00
|
|
|
|
rt_hw_interrupt_enable(level);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int console_getc(struct rt_serial_device *serial)
|
|
|
|
|
{
|
|
|
|
|
char ch;
|
|
|
|
|
struct console_uart* uart;
|
|
|
|
|
|
|
|
|
|
RT_ASSERT(serial != RT_NULL);
|
|
|
|
|
uart = (struct console_uart *)serial->parent.user_data;
|
|
|
|
|
|
|
|
|
|
if (rt_ringbuffer_getchar(&(uart->rb), &ch)) return ch;
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const struct rt_uart_ops console_uart_ops =
|
|
|
|
|
{
|
|
|
|
|
console_configure,
|
|
|
|
|
console_control,
|
|
|
|
|
console_putc,
|
|
|
|
|
console_getc,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int uart_console_init(void)
|
|
|
|
|
{
|
|
|
|
|
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
|
|
|
|
|
struct console_uart* uart;
|
|
|
|
|
struct rt_serial_device* serial;
|
|
|
|
|
|
|
|
|
|
uart = &_console_uart;
|
|
|
|
|
serial = &_serial;
|
|
|
|
|
|
|
|
|
|
uart->rx_ready = 0;
|
|
|
|
|
|
|
|
|
|
serial->ops = &console_uart_ops;
|
|
|
|
|
serial->config = config;
|
|
|
|
|
/* initialize ring buffer */
|
|
|
|
|
rt_ringbuffer_init(&uart->rb, uart->rx_buffer, sizeof(uart->rx_buffer));
|
|
|
|
|
|
|
|
|
|
/* register UART device */
|
|
|
|
|
rt_hw_serial_register(serial, "console",
|
|
|
|
|
RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
|
|
|
|
|
uart);
|
|
|
|
|
|
|
|
|
|
console_lowlevel_init();
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|