mirror of
https://github.com/peterantypas/maiana.git
synced 2025-05-18 00:10:08 -07:00
187 lines
4.5 KiB
C++
187 lines
4.5 KiB
C++
/*
|
|
* Terminal.cpp
|
|
*
|
|
* Created on: Apr 19, 2016
|
|
* Author: peter
|
|
*/
|
|
|
|
#include "DataTerminal.hpp"
|
|
|
|
#include "stm32f30x.h"
|
|
#include "printf2.h"
|
|
#include "MenuScreens.hpp"
|
|
#include "Events.hpp"
|
|
#include <stdio.h>
|
|
#include "Utils.hpp"
|
|
#include <cstring>
|
|
|
|
#ifdef ENABLE_TERMINAL
|
|
|
|
static char __buff[128];
|
|
|
|
DataTerminal &DataTerminal::instance()
|
|
{
|
|
static DataTerminal __instance;
|
|
return __instance;
|
|
}
|
|
|
|
void DataTerminal::init()
|
|
{
|
|
GPIO_InitTypeDef GPIO_InitStruct;
|
|
NVIC_InitTypeDef NVIC_InitStruct;
|
|
|
|
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); // For USART3
|
|
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_7);
|
|
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_7);
|
|
|
|
// Initialize pins as alternative function 7 (USART)
|
|
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
|
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
|
|
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
|
|
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_Level_1;
|
|
GPIO_Init(GPIOB, &GPIO_InitStruct);
|
|
|
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
|
|
|
|
|
|
USART_InitTypeDef USART_InitStructure;
|
|
USART_StructInit(&USART_InitStructure);
|
|
|
|
USART_InitStructure.USART_BaudRate = 38400;
|
|
USART_Init(USART3, &USART_InitStructure);
|
|
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
|
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
|
|
USART_InitStructure.USART_Parity = USART_Parity_No;
|
|
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
|
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
|
|
|
USART_Cmd(USART3, ENABLE);
|
|
|
|
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
|
|
NVIC_InitStruct.NVIC_IRQChannel = USART3_IRQn;
|
|
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
|
|
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 5;
|
|
NVIC_Init(&NVIC_InitStruct);
|
|
}
|
|
|
|
DataTerminal::DataTerminal()
|
|
: mCmdBuffPos(0)
|
|
{
|
|
mCmdTokens.reserve(5);
|
|
EventQueue::instance().addObserver(this, RESPONSE_EVENT);
|
|
}
|
|
|
|
void DataTerminal::processEvent(const Event &e)
|
|
{
|
|
switch (e.type) {
|
|
case RESPONSE_EVENT:
|
|
sprintf(__buff, "[%s]%s\r\n", (e.response.success ? "OK" : "ERR"), e.response.data);
|
|
write("RESPONSE", __buff);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void DataTerminal::processCharacter(char c)
|
|
{
|
|
if ( c == 13 ) {
|
|
mCmdBuffer[mCmdBuffPos] = 0;
|
|
mCmdBuffPos = 0;
|
|
processCommand();
|
|
}
|
|
else {
|
|
mCmdBuffer[mCmdBuffPos++] = c;
|
|
if (mCmdBuffPos >= sizeof mCmdBuffer)
|
|
mCmdBuffPos = 0;
|
|
|
|
}
|
|
}
|
|
|
|
void DataTerminal::processCommand()
|
|
{
|
|
string s(mCmdBuffer);
|
|
Utils::trim(s);
|
|
Utils::tokenize(s, ' ', mCmdTokens);
|
|
|
|
if ( mCmdTokens[0] == "set" && mCmdTokens.size() >= 3 ) {
|
|
// TODO: Extract field and value and queue a command event
|
|
Event *e = EventPool::instance().newEvent(REQUEST_EVENT);
|
|
e->request.operation = OP_SET;
|
|
strncpy(e->request.field, mCmdTokens[1].c_str(), sizeof e->request.field);
|
|
strncpy(e->request.value, mCmdTokens[2].c_str(), sizeof e->request.value);
|
|
EventQueue::instance().push(e);
|
|
}
|
|
else if ( mCmdTokens[0] == "get" && mCmdTokens.size() >= 2 ) {
|
|
// TODO: Extract field
|
|
Event *e = EventPool::instance().newEvent(REQUEST_EVENT);
|
|
e->request.operation = OP_GET;
|
|
strncpy(e->request.field, mCmdTokens[1].c_str(), sizeof e->request.field);
|
|
EventQueue::instance().push(e);
|
|
}
|
|
}
|
|
|
|
void write_char(USART_TypeDef* USARTx, char c)
|
|
{
|
|
while (!(USARTx->ISR & 0x00000040))
|
|
;
|
|
|
|
USART_SendData(USARTx, c);
|
|
}
|
|
|
|
#ifdef MULTIPLEXED_OUTPUT
|
|
|
|
void DataTerminal::write(const char *cls, const char* s)
|
|
{
|
|
write_char(USART3, '[');
|
|
for ( size_t i = 0; i < strlen(cls); ++i )
|
|
write_char(USART3, cls[i]);
|
|
write_char(USART3, ']');
|
|
|
|
for ( int i = 0; s[i] != 0; ++i )
|
|
write_char(USART3, s[i]);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void DataTerminal::write(const char* s, bool interactive)
|
|
{
|
|
if ( mInteractive && !interactive )
|
|
return;
|
|
|
|
for ( int i = 0; s[i] != 0; ++i )
|
|
write_char(USART3, s[i]);
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
void DataTerminal::_write(const char *s)
|
|
{
|
|
#ifdef MULTIPLEXED_OUTPUT
|
|
write("", s);
|
|
#else
|
|
write(s);
|
|
#endif
|
|
}
|
|
|
|
|
|
extern "C" {
|
|
|
|
void USART3_IRQHandler(void)
|
|
{
|
|
if ( USART_GetITStatus(USART3, USART_IT_RXNE) ) {
|
|
char c = (char) USART3->RDR; // This clears the interrupt right away
|
|
DataTerminal::instance().processCharacter(c);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|