initial stc rpn calculator project

This commit is contained in:
Jeff Wang
2019-03-20 00:34:51 -04:00
commit f4f70853c1
10 changed files with 1314 additions and 0 deletions

270
src/lcd.c Normal file
View File

@ -0,0 +1,270 @@
//#define DEBUG
#include "stc15.h"
#include "utils.h"
#include "lcd.h"
#define LCDINC 2
#define LCDDEC 0
#define LCDSHIFT 1
#define LCDNOSHIFT 0
#define LCDCURSOR 2
#define LCDNOCURSOR 0
#define LCDBLINK 1
#define LCDNOBLINK 0
#define LCDSCROLL 8
#define LCDNOSCROLL 0
#define LCDLEFT 0
#define LCDRIGHT 4
#define LCD2LINE 8
#define LCD1LINE 0
#define LCD10DOT 4
#define LCD7DOT 0
#define CR 13 // \r
#define TAB 9 // \n
#define LF 10 // \r
static int row, col;
static int OpenFlag = 0;
static int ErrorTimeout = 0;
static int Error = 0;
#define CLEAR_BIT(port, bit) (port &= ~(_BV(bit)))
#define CLEAR_BITS(port, bits) (port &= ~(bits))
#define SET_BIT(port, bit) (port |= _BV(bit))
//#define DISABLE_INTERRUPTS() __critical{
//#define ENABLE_INTERRUPTS() }
#define DISABLE_INTERRUPTS() {
#define ENABLE_INTERRUPTS() }
#define LCD_E P3_5
#define LCD_RW P3_6
#define LCD_RS P3_7
#define LCD_BUSY P2_7 //LCD D7
static void outCsrBlindNibble(unsigned char command);
static void outCsrBlind(unsigned char command);
static void outCsr(unsigned char command);
static char readBusy(void);
static void wait_busy(void);
static void to_row(unsigned char row_to);
static void LCD_OutChar(unsigned char c);
static void outCsrBlindNibble(unsigned char command) {
// CLEAR_BITS(PORTC, _BV(LCD_E) | _BV(LCD_RS) | _BV(LCD_RW));
P3 &= ~(0x7 << 5); //clear LCD_E, LCD_RS, LCD_RW
_delay_us(50);
P2 = ((command & 0xf) << 4);
//CLEAR_BIT(PORTC, LCD_E); //E = 0
//CLEAR_BIT(PORTC, LCD_RS); //control
//CLEAR_BIT(PORTC, LCD_RW); //write
_delay_us(100);
LCD_E = 1;
_delay_us(100);
LCD_E = 0;
}
static void outCsrBlind(unsigned char command) {
outCsrBlindNibble(command >> 4); // ms nibble, E=0, RS=0
_delay_us(100);
outCsrBlindNibble(command); // ls nibble, E=0, RS=0
_delay_us(100); // blind cycle 90 us wait
}
static void outCsr(unsigned char command) {
DISABLE_INTERRUPTS();
outCsrBlindNibble(command >> 4); // ms nibble, E=0, RS=0
outCsrBlindNibble(command); // ls nibble, E=0, RS=0
ENABLE_INTERRUPTS();
wait_busy();
}
#define SET_BUSY_IN() do {P2M1 |= (1<<7); P2M0 &= ~(1<<7);} while(0)
#define SET_BUSY_OUT() do {P2M1 &= ~(1<<7); P2M0 |= (1<<7); } while(0)
//returns 1 if busy, 0 otherwise
static char readBusy() {
unsigned char oldP2 = P2;
__bit busy;
LCD_RS = 0; //control
LCD_RW = 1; //read
LCD_E = 1;
SET_BUSY_IN();
//wait
_delay_us(100); // blind cycle 100us wait
//read busy flag
busy = LCD_BUSY;
SET_BUSY_OUT();
LCD_E = 0;
LCD_E = 1;
//wait
_delay_us(100); // blind cycle 100us wait
LCD_E = 0;
P2 = oldP2;
return busy;
}
//sets ErrorTimeout flag if busy signal not cleared in time
static void wait_busy() {
unsigned int i;
for (i = 0; i < 100; i++){
if (!readBusy()){
return;
}
_delay_ms(1);
}
ErrorTimeout = 1;
return;
}
static void LCD_OutChar(unsigned char c) {
unsigned char lower = (c & 0x0f);
DISABLE_INTERRUPTS();
wait_busy();
//output upper 4 bits:
LCD_E = 0;
LCD_RS = 1; //data
LCD_RW = 0; //write
P2 = ((c & 0xf0));
LCD_E = 1;
_delay_us(100);
LCD_E = 0;
//output lower 4 bits:
P2 = ((c & 0xf) << 4);
LCD_E = 1;
_delay_us(100);
LCD_E = 0;
ENABLE_INTERRUPTS();
wait_busy();
}
void LCD_Open(void) {
static int open_error = 0;
if (!OpenFlag) {
//set ports to output
//P2
P2M1 = 0;
P2M0 = 0xff;
//P3
P3M1 &= ~(0xfe);
P3M0 |= (0xfe);
_delay_ms(30); // to allow LCD powerup
outCsrBlindNibble(0x03); // (DL=1 8-bit mode)
_delay_ms(5); // blind cycle 5ms wait
outCsrBlindNibble(0x03); // (DL=1 8-bit mode)
_delay_us(100); // blind cycle 100us wait
outCsrBlindNibble(0x03); // (DL=1 8-bit mode)
_delay_us(100); // blind cycle 100us wait (not called for, but do it anyway)
outCsrBlindNibble(0x02); // DL=1 switch to 4 bit mode (only high 4 bits are sent)
_delay_us(100); // blind cycle 100 us wait
//set increment, no shift
outCsrBlind(0x4 + LCDINC + LCDNOSHIFT);
#ifdef DEBUG
//set display on, cursor on, blink on:
outCsrBlind(0x0c + LCDCURSOR + LCDBLINK);
#else
//set display on, cursor and blink off:
outCsrBlind(0x0c + LCDNOCURSOR + LCDNOBLINK);
#endif
//set display shift on and to the right
outCsrBlind(0x10 + LCDNOSCROLL + LCDRIGHT);
//set 4-bit mode, 2 line, 5x7 display:
outCsrBlind(0x20 + LCD2LINE + LCD7DOT);
//clear display
LCD_Clear();
_delay_ms(50);
if (!readBusy()) {
OpenFlag = 1;
} else {
open_error = 1;
}
} else { //display already open
open_error = 1;
}
}
//row and columns indexed from 0
void LCD_GoTo(unsigned int row_to, unsigned int col_to) {
if (row_to < MAX_ROWS && col_to < MAX_CHARS_PER_LINE) {
outCsr(0x80 + 0x40 * row_to + col_to); //set ddram address to position
row = row_to;
col = col_to;
} else {
Error = 1;
}
}
static void to_row(unsigned char row_to) {
if (row_to == 0) {
outCsr(0x80);//set address to start of row 0
row = 0;
} else {
outCsr(0xc0);// set address to row 1
row = 1;
}
col = 0;
}
//row indexed from 0
void LCD_SingleLineGoTo(unsigned int spot_to) {
LCD_GoTo(spot_to / MAX_CHARS_PER_LINE, spot_to % MAX_CHARS_PER_LINE);
}
void LCD_OutString(const char *string) {
const char *s;
for (s = string; *s; s++) {
TERMIO_PutChar(*s);
}
}
short TERMIO_PutChar(unsigned char letter) {
if (letter == CR || letter == '\n') {
LCD_Clear();
} else if (letter == TAB || letter == '\t') {
if (row == 0) {
to_row(1);
} else {
to_row(0);
}
} else {
if (col > MAX_CHARS_PER_LINE) {
if (row == 0) {
to_row(1);
} else {
to_row(0);
}
}
col++;
LCD_OutChar(letter);
}
return 1;
}
void LCD_Clear() {
if (OpenFlag) {
outCsr(0x01);
} else {
outCsrBlind(0x01);
}
row = 0;
col = 0;
}
unsigned char LCD_Timeout_Error(void) {
if (ErrorTimeout != 0) {
return 1;
}
return 0;
}

20
src/lcd.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef LCD_H
#define LCD_H
#define MAX_CHARS_PER_LINE 15
#define MAX_ROWS 2
void LCD_Open(void);
void LCD_Clear(void);
void LCD_GoTo(unsigned int row, unsigned int col);
void LCD_SingleLineGoTo(unsigned int row_to);
void LCD_OutString(const char* string);
short TERMIO_PutChar(unsigned char letter);
unsigned char LCD_Timeout_Error(void);
#endif

62
src/main.c Normal file
View File

@ -0,0 +1,62 @@
//
// STC15 RPN calculator
//
#include "stc15.h"
#include <stdint.h>
#include "lcd.h"
#include "utils.h"
#define FOSC 11059200
// clear wdt
#define WDT_CLEAR() (WDT_CONTR |= 1 << 4)
void timer0_isr() __interrupt 1 __using 1
{
P3_1 ^= 1;
}
// Call timer0_isr() 10000/sec: 0.0001 sec
// Initialize the timer count so that it overflows after 0.0001 sec
// THTL = 0x10000 - FOSC / 12 / 10000 = 0x10000 - 92.16 = 65444 = 0xFFA4
void Timer0Init(void) //100us @ 11.0592MHz
{
// TMOD = 0; // default: 16-bit auto-reload
// AUXR = 0; // default: traditional 8051 timer frequency of FOSC / 12
// Initial values of TL0 and TH0 are stored in hidden reload registers: RL_TL0 and RL_TH0
TL0 = 0xA4; // Initial timer value
TH0 = 0xFF; // Initial timer value
TF0 = 0; // Clear overflow flag
TR0 = 1; // Timer0 start run
ET0 = 1; // Enable timer0 interrupt
EA = 1; // Enable global interrupt
}
char buf[17];
/*********************************************/
int main()
{
uint32_t i;
Timer0Init(); // display refresh & switch read
LCD_Open();
P3_4 = 0; //turn on led backlight
LCD_OutString("Hello world !!!!");
LCD_GoTo(1,0);
LCD_OutString(".......");
i = 0;
// LOOP
while (1)
{
LCD_GoTo(1,7);
LCD_OutString(u32str(i, buf, 10));
i++;
WDT_CLEAR();
}
}
/* ------------------------------------------------------------------------- */

179
src/stc15.h Normal file
View File

@ -0,0 +1,179 @@
#ifndef _STC15_H_
#define _STC15_H_
#include <8051.h>
#ifdef REG8051_H
#undef REG8051_H
#endif
/* P4 */
__sfr __at (0xC0) P4 ;
__sbit __at (0xC0) P4_0 ;
__sbit __at (0xC1) P4_1 ;
__sbit __at (0xC2) P4_2 ;
__sbit __at (0xC3) P4_3 ;
__sbit __at (0xC4) P4_4 ;
__sbit __at (0xC5) P4_5 ;
__sbit __at (0xC6) P4_6 ;
__sbit __at (0xC7) P4_7 ;
__sfr __at 0x94 P0M0;
__sfr __at 0x93 P0M1;
__sfr __at 0x92 P1M0;
__sfr __at 0x91 P1M1;
__sfr __at 0x96 P2M0;
__sfr __at 0x95 P2M1;
__sfr __at 0xB2 P3M0;
__sfr __at 0xB1 P3M1;
__sfr __at 0xB4 P4M0;
__sfr __at 0xB3 P4M1;
__sfr __at 0xCA P5M0;
__sfr __at 0xC9 P5M1;
__sfr __at 0xCC P6M0;
__sfr __at 0xCB P6M1;
__sfr __at 0xE2 P7M0;
__sfr __at 0xE1 P7M1;
__sfr __at 0x8E AUXR;
__sfr __at 0xA2 AUXR1;
__sfr __at 0xA2 P_SW1;
__sfr __at 0x97 CLK_DIV;
__sfr __at 0xA1 BUS_SPEED;
__sfr __at 0x9D P1ASF;
__sfr __at 0xBA P_SW2;
/* IE */
__sbit __at 0xAE ELVD;
__sbit __at 0xAD EADC;
/* IP */
__sbit __at 0xBF PPCA;
__sbit __at 0xBE PLVD;
__sbit __at 0xBD PADC;
__sfr __at 0xAF IE2;
__sfr __at 0xB5 IP2;
__sfr __at 0x8F INT_CLKO;
__sfr __at 0xD1 T4T3M;
__sfr __at 0xD1 T3T4M;
__sfr __at 0xD2 T4H;
__sfr __at 0xD3 T4L;
__sfr __at 0xD4 T3H;
__sfr __at 0xD5 T3L;
__sfr __at 0xD6 T2H;
__sfr __at 0xD7 T2L;
__sfr __at 0xAA WKTCL;
__sfr __at 0xAB WKTCH;
__sfr __at 0xC1 WDT_CONTR;
__sfr __at 0x9A S2CON;
__sfr __at 0x9B S2BUF;
__sfr __at 0xAC S3CON;
__sfr __at 0xAD S3BUF;
__sfr __at 0x84 S4CON;
__sfr __at 0x85 S4BUF;
__sfr __at 0xA9 SADDR;
__sfr __at 0xB9 SADEN;
//ADC
__sfr __at 0xBC ADC_CONTR;
__sfr __at 0xBD ADC_RES;
__sfr __at 0xBE ADC_RESL;
//SPI
__sfr __at 0xCD SPSTAT;
__sfr __at 0xCE SPCTL;
__sfr __at 0xCF SPDAT;
//IAP/ISP
__sfr __at 0xC2 IAP_DATA;
__sfr __at 0xC3 IAP_ADDRH;
__sfr __at 0xC4 IAP_ADDRL;
__sfr __at 0xC5 IAP_CMD;
__sfr __at 0xC6 IAP_TRIG;
__sfr __at 0xC7 IAP_CONTR;
//PCA/PWM
__sfr __at 0xD8 CCON;
__sbit __at 0xDF CF;
__sbit __at 0xDE CR;
__sbit __at 0xDA CCF2;
__sbit __at 0xD9 CCF1;
__sbit __at 0xD8 CCF0;
__sfr __at 0xD9 CMOD;
__sfr __at 0xE9 CL;
__sfr __at 0xF9 CH;
__sfr __at 0xDA CCAPM0;
__sfr __at 0xDB CCAPM1;
__sfr __at 0xDC CCAPM2;
__sfr __at 0xEA CCAP0L;
__sfr __at 0xEB CCAP1L;
__sfr __at 0xEC CCAP2L;
__sfr __at 0xF2 PCA_PWM0;
__sfr __at 0xF3 PCA_PWM1;
__sfr __at 0xF4 PCA_PWM2;
__sfr __at 0xFA CCAP0H;
__sfr __at 0xFB CCAP1H;
__sfr __at 0xFC CCAP2H;
__sfr __at 0xE6 CMPCR1;
__sfr __at 0xE7 CMPCR2;
//PWM
__sfr __at 0xf1 PWMCFG;
__sfr __at 0xf5 PWMCR;
__sfr __at 0xf6 PWMIF;
__sfr __at 0xf7 PWMFDCR;
#define PWMC (*(unsigned int volatile xdata *)0xfff0)
#define PWMCH (*(unsigned char volatile xdata *)0xfff0)
#define PWMCL (*(unsigned char volatile xdata *)0xfff1)
#define PWMCKS (*(unsigned char volatile xdata *)0xfff2)
#define PWM2T1 (*(unsigned int volatile xdata *)0xff00)
#define PWM2T1H (*(unsigned char volatile xdata *)0xff00)
#define PWM2T1L (*(unsigned char volatile xdata *)0xff01)
#define PWM2T2 (*(unsigned int volatile xdata *)0xff02)
#define PWM2T2H (*(unsigned char volatile xdata *)0xff02)
#define PWM2T2L (*(unsigned char volatile xdata *)0xff03)
#define PWM2CR (*(unsigned char volatile xdata *)0xff04)
#define PWM3T1 (*(unsigned int volatile xdata *)0xff10)
#define PWM3T1H (*(unsigned char volatile xdata *)0xff10)
#define PWM3T1L (*(unsigned char volatile xdata *)0xff11)
#define PWM3T2 (*(unsigned int volatile xdata *)0xff12)
#define PWM3T2H (*(unsigned char volatile xdata *)0xff12)
#define PWM3T2L (*(unsigned char volatile xdata *)0xff13)
#define PWM3CR (*(unsigned char volatile xdata *)0xff14)
#define PWM4T1 (*(unsigned int volatile xdata *)0xff20)
#define PWM4T1H (*(unsigned char volatile xdata *)0xff20)
#define PWM4T1L (*(unsigned char volatile xdata *)0xff21)
#define PWM4T2 (*(unsigned int volatile xdata *)0xff22)
#define PWM4T2H (*(unsigned char volatile xdata *)0xff22)
#define PWM4T2L (*(unsigned char volatile xdata *)0xff23)
#define PWM4CR (*(unsigned char volatile xdata *)0xff24)
#define PWM5T1 (*(unsigned int volatile xdata *)0xff30)
#define PWM5T1H (*(unsigned char volatile xdata *)0xff30)
#define PWM5T1L (*(unsigned char volatile xdata *)0xff31)
#define PWM5T2 (*(unsigned int volatile xdata *)0xff32)
#define PWM5T2H (*(unsigned char volatile xdata *)0xff32)
#define PWM5T2L (*(unsigned char volatile xdata *)0xff33)
#define PWM5CR (*(unsigned char volatile xdata *)0xff34)
#define PWM6T1 (*(unsigned int volatile xdata *)0xff40)
#define PWM6T1H (*(unsigned char volatile xdata *)0xff40)
#define PWM6T1L (*(unsigned char volatile xdata *)0xff41)
#define PWM6T2 (*(unsigned int volatile xdata *)0xff42)
#define PWM6T2H (*(unsigned char volatile xdata *)0xff42)
#define PWM6T2L (*(unsigned char volatile xdata *)0xff43)
#define PWM6CR (*(unsigned char volatile xdata *)0xff44)
#define PWM7T1 (*(unsigned int volatile xdata *)0xff50)
#define PWM7T1H (*(unsigned char volatile xdata *)0xff50)
#define PWM7T1L (*(unsigned char volatile xdata *)0xff51)
#define PWM7T2 (*(unsigned int volatile xdata *)0xff52)
#define PWM7T2H (*(unsigned char volatile xdata *)0xff52)
#define PWM7T2L (*(unsigned char volatile xdata *)0xff53)
#define PWM7CR (*(unsigned char volatile xdata *)0xff54)
#endif

47
src/utils.c Normal file
View File

@ -0,0 +1,47 @@
#include <stdint.h>
void _delay_ms(uint8_t ms)
{
// delay function, tuned for 11.092 MHz clock
// optimized to assembler
ms; // keep compiler from complaining?
__asm;
; dpl contains ms param value
delay$:
mov b, #8 ; i
outer$:
mov a, #243 ; j
inner$:
djnz acc, inner$
djnz b, outer$
djnz dpl, delay$
__endasm;
}
char* u32str(uint32_t x, char* buf, uint8_t base)
{
int i = 0, j;
//corner case
if (x == 0){
buf[i] = '0';
}
//get reversed string
while(x > 0){
buf[i] = (x % base) + '0';
x /= base;
i++;
}
//add terminator
buf[i] = '\0';
i--; //back to last digit
//reverse string
for (j = 0; j < i; j++, i--){
char tmp;
tmp = buf[j];
buf[j] = buf[i];
buf[i] = tmp;
}
return buf;
}

21
src/utils.h Normal file
View File

@ -0,0 +1,21 @@
/*
* utils.h
*
* Created on: Mar 10, 2019
*/
#ifndef SRC_UTILS_H_
#define SRC_UTILS_H_
#include <stdint.h>
void _delay_ms(uint8_t ms);
//TODO
#define _delay_us(x) _delay_ms(1)
char* u32str(uint32_t x, char* buf, uint8_t base);
#endif /* SRC_UTILS_H_ */