start working on gui

This commit is contained in:
Jeff Wang 2019-04-03 00:07:15 -04:00
parent 5cea4807f7
commit 8f39958679
10 changed files with 244 additions and 2 deletions

7
CMakeLists.txt Normal file
View File

@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 2.8)
# 3rd party tools
find_package(Qt5 COMPONENTS Widgets Qml Quick REQUIRED)
# Directory with source code
add_subdirectory(src)
add_subdirectory(qt_gui)

View File

@ -1,6 +1,6 @@
# STC DIY Calculator Firmware
This is a replacement firmware for the [diyleyuan calculator](http://www.diyleyuan.com/jc/L8Q.html). The calculator uses an STC IAP15W413AS microcontroller (an 8051 instruction set-compatible microcontorller) with a built in serial bootloder. This project uses SDCC to compile the C code and [stcgal](https://github.com/grigorig/stcgal) to load the new firmware.
This is a replacement firmware for the [diyleyuan calculator](http://www.diyleyuan.com/jc/L8Q.html). The calculator is available for purchase for less than $13 shipped from eBay by searching for "diy calculator kit". The calculator uses an STC IAP15W413AS microcontroller (an 8051 instruction set-compatible microcontorller) with a built in serial bootloder. This project uses SDCC to compile the C code and [stcgal](https://github.com/grigorig/stcgal) to load the new firmware.
![calculator](./calc.jpg)
@ -10,7 +10,8 @@ This is a replacement firmware for the [diyleyuan calculator](http://www.diyleyu
- (you must already have SDCC installed and setup so it can be found in your PATH)
- this will create a `main.hex` output file
- there is also a prebuilt binary checked in at `binaries/main.hex`
<!-- - CMakeLists.txt is for building the Qt desktop application. -->
- CMakeLists.txt is for building the Qt desktop application.
- (still a work in progress, currently doesn't do anything)
# Installing
The STC microcontroller used has a bootloader permanently stored in ROM that allows downloading new firmware over a serial port. You can re-program it using a USB-to-logic-level-serial (5V) dongle, and the stcgal program. WARNING: a lot of USB-to-logic-level-serial dongles are for 3.3V logic levels. The diyleyuan calculator runs at 5V to make it easier to power/drive the LCD display. You have a couple of options:

29
qt_gui/CMakeLists.txt Normal file
View File

@ -0,0 +1,29 @@
include_directories(${Qt5Widgets_INCLUDE_DIRS} ${QtQml_INCLUDE_DIRS})
add_definitions(${Qt5Widgets_DEFINITIONS} ${QtQml_DEFINITIONS} ${${Qt5Quick_DEFINITIONS}})
qt5_add_resources(QT_RESOURCES main.qrc)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(PROJECT "RPN_Calculator")
project(${PROJECT})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -std=c++11 -fstrict-aliasing -pedantic ")
if(NOT DEFINED HEADERS)
file(GLOB HEADERS ${CMAKE_CURRENT_SOURCE_DIR}*.h)
endif()
# if(NOT DEFINED SOURCES)
# file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}*.cpp)
# endif()
source_group("Header Files" FILES ${HEADERS})
# source_group("Source Files" FILES ${SOURCES})
set(SOURCES main.cpp calculator.cpp)
add_executable(${PROJECT} ${HEADERS} ${SOURCES} ${QT_RESOURCES})
target_link_libraries(${PROJECT}
Qt5::Widgets
Qt5::Qml
Qt5::Quick
calc
)

12
qt_gui/calculator.cpp Normal file
View File

@ -0,0 +1,12 @@
#include <QDebug>
#include "calculator.h"
Calculator::Calculator(QObject *parent) :
QObject(parent)
{
}
void Calculator::buttonClicked(const QString& in) {
qDebug() << in;
}

20
qt_gui/calculator.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef QTGUI_CALCULATOR_H
#define QTGUI_CALCULATOR_H
#include <QObject>
class Calculator : public QObject
{
Q_OBJECT
public:
explicit Calculator(QObject *parent = 0);
public slots:
void buttonClicked(const QString& in);
};
#endif //include guard

16
qt_gui/main.cpp Normal file
View File

@ -0,0 +1,16 @@
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "calculator.h"
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
Calculator calculator;
engine.rootContext()->setContextProperty("_calculator", &calculator);
return app.exec();
}

55
qt_gui/main.qml Normal file
View File

@ -0,0 +1,55 @@
import QtQuick 2.0
import QtQuick.Controls 1.0
import Qt3D.Input 2.0
ApplicationWindow
{
visible: true
width: 1000
height: 1000
title: qsTr("RPN Calculator")
//calculator
Column {
id: base;
spacing: 5;
width: 4 * (100 + 5)
height: 5 * (100 + 5) + 200
//LCD
Rectangle {
id: lcd;
color: "gray"
width: 4 * (100 + 5) - 5
height: 200
}
//Keyboard
Repeater {
model: 5;
//row
delegate: Row {
id: key_row;
spacing: 5;
//keys within row
Repeater {
model: 4;
delegate: Rectangle {
id: key_key;
width: 100;
height: 100;
color: "blue"
border { width: 1; color: "black" }
Text {
text: index
anchors.centerIn: parent
}
MouseHandler {
onClicked: _calculator.buttonClicked(index)
}
}
}
}
}
}
}

5
qt_gui/main.qrc Normal file
View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
</RCC>

4
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,4 @@
add_library(decn decn/decn.c)
add_library(calc main.c calc.c utils.c lcd_emulator.c key.c)

93
src/lcd_emulator.c Normal file
View File

@ -0,0 +1,93 @@
/*
* lcd_emulator.c
*
* Created on: Apr 1, 2019
*/
#include <stdio.h>
#include <stdint.h>
#include "lcd.h"
#define CR 13 // \r
#define TAB 9 // \n
static int lcd_row, lcd_col;
static char lcd_buf[MAX_ROWS][MAX_CHARS_PER_LINE];
void LCD_Open(void){
}
void LCD_Clear(void){
lcd_row=0;
lcd_col=0;
for (int i = 0; i < MAX_ROWS; i++){
for (int j = 0; j < MAX_CHARS_PER_LINE; j++){
lcd_buf[i][j] = 0;
}
}
}
void LCD_GoTo(unsigned int row, unsigned int col){
if (row < MAX_ROWS && col < MAX_CHARS_PER_LINE){
lcd_row = row;
lcd_col = col;
} else {
printf("LCD_GoTo(%u, %u) out of range\n", lcd_row, lcd_col);
}
}
static void to_row(unsigned char row_to){
if (row_to == 0){
lcd_row = 0;
} else {
lcd_row = 1;
}
lcd_col = 0;
}
void LCD_OutString(const char *string, uint8_t max_chars) {
const char *s;
for (s = string; *s && max_chars > 0; s++, max_chars--) {
TERMIO_PutChar(*s);
}
}
short TERMIO_PutChar(unsigned char letter) {
if (letter == CR || letter == '\n') {
LCD_Clear();
} else if (letter == TAB || letter == '\t') {
if (lcd_row == 0) {
to_row(1);
} else {
to_row(0);
}
} else {
lcd_buf[lcd_row][lcd_col] = letter;
lcd_col++;
if (lcd_col > MAX_CHARS_PER_LINE) {
if (lcd_row == 0) {
to_row(1);
} else {
to_row(0);
}
}
}
return 1;
}
void LCD_ClearToEnd(uint8_t curr_row){
while (lcd_col != 0 && lcd_row == curr_row){
TERMIO_PutChar(' ');
}
}
void LCD_OutNibble(uint8_t x){
x &= 0xf; //ensure only bottom nibble
if (x <= 9){
TERMIO_PutChar(x + '0');
} else {
TERMIO_PutChar(x - 10 + 'a');
}
}