From bfac338ef2b5706ab509454863da97369f18357a Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Mon, 10 Jun 2024 11:43:06 +0900 Subject: [PATCH] [TMS7000] Add TMS700x Serial handler --- debugger/tms7000/devs_tms7000.cpp | 13 + debugger/tms7000/devs_tms7000.h | 8 + debugger/tms7000/pins_tms7000.cpp | 10 +- debugger/tms7000/tms7002_serial_handler.cpp | 61 ++++ debugger/tms7000/tms7002_serial_handler.h | 39 ++ samples/tms7000/Makefile | 3 +- samples/tms7000/serial.asm | 43 +++ samples/tms7000/serial.hex | 4 + samples/tms7000/serial.lst | 149 ++++++++ samples/tms7000/serialir.asm | 74 ++++ samples/tms7000/serialir.hex | 10 + samples/tms7000/serialir.lst | 281 +++++++++++++++ samples/tms7000/serialitr.asm | 173 +++++++++ samples/tms7000/serialitr.hex | 14 + samples/tms7000/serialitr.lst | 380 ++++++++++++++++++++ samples/tms7000/tms7001.inc | 30 +- samples/tms7000/tms70c02.inc | 11 +- 17 files changed, 1292 insertions(+), 11 deletions(-) create mode 100644 debugger/tms7000/tms7002_serial_handler.cpp create mode 100644 debugger/tms7000/tms7002_serial_handler.h create mode 100644 samples/tms7000/serial.asm create mode 100644 samples/tms7000/serial.hex create mode 100644 samples/tms7000/serial.lst create mode 100644 samples/tms7000/serialir.asm create mode 100644 samples/tms7000/serialir.hex create mode 100644 samples/tms7000/serialir.lst create mode 100644 samples/tms7000/serialitr.asm create mode 100644 samples/tms7000/serialitr.hex create mode 100644 samples/tms7000/serialitr.lst diff --git a/debugger/tms7000/devs_tms7000.cpp b/debugger/tms7000/devs_tms7000.cpp index 973a5766..5b5354bd 100644 --- a/debugger/tms7000/devs_tms7000.cpp +++ b/debugger/tms7000/devs_tms7000.cpp @@ -11,6 +11,8 @@ DevsTms7000 Devs; void DevsTms7000::reset() { ACIA.reset(); ACIA.setBaseAddr(ACIA_BASE); + if (_serial) + _serial->reset(); } void DevsTms7000::begin() { @@ -21,6 +23,11 @@ void DevsTms7000::loop() { ACIA.loop(); } +void DevsTms7000::setIdle(bool idle) { + if (_serial) + _serial->setIdle(idle); +} + bool DevsTms7000::isSelected(uint32_t addr) const { return ACIA.isSelected(addr); } @@ -36,15 +43,21 @@ void DevsTms7000::write(uint32_t addr, uint16_t data) const { Device &DevsTms7000::parseDevice(const char *name) const { if (strcasecmp(name, ACIA.name()) == 0) return ACIA; + if (_serial && strcasecmp(name, _serial->name()) == 0) + return *_serial; return Devs::nullDevice(); } void DevsTms7000::enableDevice(Device &dev) { ACIA.enable(&dev == &ACIA); + if (_serial) + _serial->enable(&dev == _serial); } void DevsTms7000::printDevices() const { printDevice(ACIA); + if (_serial) + printDevice(*_serial); } } // namespace tms7000 diff --git a/debugger/tms7000/devs_tms7000.h b/debugger/tms7000/devs_tms7000.h index 54005b63..0d18f855 100644 --- a/debugger/tms7000/devs_tms7000.h +++ b/debugger/tms7000/devs_tms7000.h @@ -2,6 +2,7 @@ #define __DEVS_TMS7000_H__ #include "devs.h" +#include "serial_handler.h" #define ACIA_BASE 0x01F0 // P240 @@ -9,9 +10,11 @@ namespace debugger { namespace tms7000 { struct DevsTms7000 : Devs { + DevsTms7000() : Devs(), _serial(nullptr) {} void begin() override; void reset() override; void loop() override; + void setIdle(bool idle) override; bool isSelected(uint32_t addr) const override; uint16_t read(uint32_t addr) const override; void write(uint32_t addr, uint16_t data) const override; @@ -19,6 +22,11 @@ struct DevsTms7000 : Devs { Device &parseDevice(const char *name) const override; void enableDevice(Device &dev) override; void printDevices() const override; + + void setSerialHandler(SerialHandler *serial) { _serial = serial; } + +private: + SerialHandler *_serial; }; extern struct DevsTms7000 Devs; diff --git a/debugger/tms7000/pins_tms7000.cpp b/debugger/tms7000/pins_tms7000.cpp index 4160cbf4..569bef0c 100644 --- a/debugger/tms7000/pins_tms7000.cpp +++ b/debugger/tms7000/pins_tms7000.cpp @@ -6,10 +6,13 @@ #include "mems_tms7000.h" #include "regs_tms7000.h" #include "signals_tms7000.h" +#include "tms7002_serial_handler.h" namespace debugger { namespace tms7000 { +using tms7002::SerialH; + struct PinsTms7000 Pins; // clang-format off @@ -48,6 +51,7 @@ constexpr auto clk2_hi_ns = 500; constexpr auto clk2_lo_ns = 500; constexpr auto clk4_hi_ns = 250; constexpr auto clk4_lo_ns = 250; +constexpr auto clk4_hi_serial = 200; inline void clkin_hi() { digitalWriteFast(PIN_CLKIN, HIGH); @@ -124,6 +128,7 @@ inline void clkin_cycle() { void clk2_hi() { clkin_hi(); + SerialH.loop(); } void clk2_lo() { @@ -132,7 +137,8 @@ void clk2_lo() { void clk4_hi() { clkin_lo(); - delayNanoseconds(clk4_hi_ns); + delayNanoseconds(clk4_hi_serial); + SerialH.loop(); clkin_hi(); } @@ -239,6 +245,8 @@ void PinsTms7000::checkHardwareType() { _hardType = port19->external() ? HW_TMS7002 : HW_TMS70C02; } Regs.restoreA(); + SerialH.setTms7001(_hardType == HW_TMS7001); + Devs.setSerialHandler(_hardType == HW_TMS7000 ? nullptr : &SerialH); } Signals *PinsTms7000::prepareCycle() const { diff --git a/debugger/tms7000/tms7002_serial_handler.cpp b/debugger/tms7000/tms7002_serial_handler.cpp new file mode 100644 index 00000000..c0a0727a --- /dev/null +++ b/debugger/tms7000/tms7002_serial_handler.cpp @@ -0,0 +1,61 @@ +#include "tms7002_serial_handler.h" +#include "debugger.h" +#include "pins_tms7000.h" +#include "regs_tms7000.h" + +namespace debugger { +namespace tms7002 { + +struct Tms7002SerialHandler SerialH; + +using tms7000::Regs; + +const char *Tms7002SerialHandler::name() const { + return "Serial"; +} + +const char *Tms7002SerialHandler::description() const { + return Regs.cpuName(); +} + +uint32_t Tms7002SerialHandler::baseAddr() const { + return 0x0111; // SMODE/SCTL0/SSTAT +} + +void Tms7002SerialHandler::assert_rxd() const { + digitalWriteFast(PIN_PA5, LOW); +} + +void Tms7002SerialHandler::negate_rxd() const { + digitalWriteFast(PIN_PA5, HIGH); +} + +uint8_t Tms7002SerialHandler::signal_txd() const { + return digitalReadFast(PIN_PB3); +} + +void Tms7002SerialHandler::resetHandler() { + pinMode(PIN_PA5, OUTPUT); + pinMode(PIN_PB3, INPUT); + // TMS7002/TMS7001 Serial: + // fosc: XTAL frequency + // CLK: system clock; fosc/2 (/2 clock option), fosc/4 (/4 clock option) + // PR: Timer 3 prescaler reload value + // TR: TImer 3 reload value + // Serial Clock (SCLK) = (CLK / 2) / (PR + 1) / (TR + 1) / 2 + // Asynchronous baud rate; SCLK/8 (TMS7002), SCLK/16 (TMS7001) + constexpr auto PR = 0; + constexpr auto TR = 12; + _pre_divider = (PR + 1) * (TR + 1) * 4 * 2; + _divider = _tms7001 ? 16 : 8; +} + +} // namespace tms7002 +} // namespace debugger + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/debugger/tms7000/tms7002_serial_handler.h b/debugger/tms7000/tms7002_serial_handler.h new file mode 100644 index 00000000..7a78d4e7 --- /dev/null +++ b/debugger/tms7000/tms7002_serial_handler.h @@ -0,0 +1,39 @@ +#ifndef __TMS7002_SERIAL_HANDLER_H__ +#define __TMS7002_SERIAL_HANDLER_H__ + +#include "serial_handler.h" + +namespace debugger { +namespace tms7002 { + +struct Tms7002SerialHandler final : SerialHandler { + Tms7002SerialHandler() : SerialHandler(), _tms7001(false) {} + + const char *name() const override; + const char *description() const override; + uint32_t baseAddr() const override; + + void setTms7001(bool tms7001) { _tms7001 = tms7001; } + +protected: + void resetHandler() override; + void assert_rxd() const override; + void negate_rxd() const override; + uint8_t signal_txd() const override; + +private: + bool _tms7001; +}; + +extern struct Tms7002SerialHandler SerialH; + +} // namespace tms7002 +} // namespace debugger +#endif + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/samples/tms7000/Makefile b/samples/tms7000/Makefile index ce6d26eb..bf43e18f 100644 --- a/samples/tms7000/Makefile +++ b/samples/tms7000/Makefile @@ -2,7 +2,8 @@ ASM=asm .PHONY: clean -all: echo.hex echoir.hex echoitr.hex arith.hex mandelbrot.hex +all: echo.hex echoir.hex echoitr.hex arith.hex mandelbrot.hex \ + serial.hex serialir.hex serialitr.hex %.hex: %.asm $(ASM) -l $*.lst -o $@ $^ diff --git a/samples/tms7000/serial.asm b/samples/tms7000/serial.asm new file mode 100644 index 00000000..bb7679bc --- /dev/null +++ b/samples/tms7000/serial.asm @@ -0,0 +1,43 @@ +;;; -*- mode: asm; mode: flyspell-prog; -*- + cpu tms7000 + include "tms7001.inc" + + org VEC_RESET + data initialize + + org >1000 +initialize: + orp %?1000, BPORT Pass through TXD (PB3=1) + movp %0, SMODE Select SCTL0 + movp %UR_bm, SCTL0 Select SMODE by reset + movp %CMODE_bm|CHAR8_bm|ASYNC_bm, SMODE 8 bits asynchronous + movp %RXEN_bm|TXEN_bm, SCTL0 Rx/Tx enable + movp %12, T3DATA 9600 bps (TR) + movp %CLK_bm, SCTL1 Enable internal clock, PR=0 + +loop: call @getchar + tsta + jeq halt_to_system +echo: call @putchar + cmp %>0D, A + jne loop + mov %>0A, A + jmp echo +halt_to_system: + idle + +getchar: + btjzp %RXRDY_bm, SSTAT, getchar + movp RXBUF, A + rets + +putchar: + btjzp %TXRDY_bm, SSTAT, putchar + movp A, TXBUF + rets + + *** Local Variables: + *** mode: asm + *** mode: flyspell-prog + *** comment-start: "*" + *** End: diff --git a/samples/tms7000/serial.hex b/samples/tms7000/serial.hex new file mode 100644 index 00000000..e37b69ba --- /dev/null +++ b/samples/tms7000/serial.hex @@ -0,0 +1,4 @@ +:20100000A40806A20011A24011A24E11A20511A20C14A240158E1027B0E20B8E102E2D0D9E +:15102000E6F3220AE0F501A70211FC80160AA70111FC82170A32 +:02FFFE001000F1 +:00000001FF diff --git a/samples/tms7000/serial.lst b/samples/tms7000/serial.lst new file mode 100644 index 00000000..f23738cd --- /dev/null +++ b/samples/tms7000/serial.lst @@ -0,0 +1,149 @@ + 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- + 0 : cpu tms7000 + 0 : include "tms7001.inc" +(1) 0 : *** -*- mode: asm; mode: flyspell-prog; -*- +(1) 0 : include "tms7000.inc" +(2) 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(2) 0 : *** TMS7000 +(2) 0 : *** Status Register +(2) 0 : =80 ST_CARRY: equ ?10000000 set to 1 if carry occurred +(2) 0 : =40 ST_NEGATIVE: equ ?01000000 set to 1 if result is negative +(2) 0 : =20 ST_ZERO: equ ?00100000 set to 1 if result is zero +(2) 0 : =10 ST_INT: equ ?00010000 if 1, interrupt is enabled +(2) 0 : *** Vector +(2) 0 : =FFF8 VEC_INT3: equ >FFF8 #INT3 interrupt +(2) 0 : =FFFA VEC_INT2: equ >FFFA Timer 1 +(2) 0 : =FFFC VEC_INT1: equ >FFFC #INT1 interrupt +(2) 0 : =FFFE VEC_RESET: equ >FFFE #RESET vector +(2) 0 : *** Trap Vector +(2) 0 : =FFFE VEC_TRAP0: equ VEC_RESET +(2) 0 : =FFFC VEC_TRAP1: equ VEC_INT1 +(2) 0 : =FFFA VEC_TRAP2: equ VEC_INT2 +(2) 0 : =FFF8 VEC_TRAP3: equ VEC_INT3 +(2) 0 : =FFF6 VEC_TRAP4: equ >FFF6 +(2) 0 : =FFF4 VEC_TRAP5: equ >FFF4 +(2) 0 : =FFF2 VEC_TRAP6: equ >FFF2 +(2) 0 : =FFF0 VEC_TRAP7: equ >FFF0 +(2) 0 : =FFEE VEC_TRAP8: equ >FFEE +(2) 0 : =FFEC VEC_TRAP9: equ >FFEC +(2) 0 : =FFEA VEC_TRAP10: equ >FFEA +(2) 0 : =FFE8 VEC_TRAP11: equ >FFE8 +(2) 0 : =FFE6 VEC_TRAP12: equ >FFE6 +(2) 0 : =FFE4 VEC_TRAP13: equ >FFE4 +(2) 0 : =FFE2 VEC_TRAP14: equ >FFE2 +(2) 0 : =FFE0 VEC_TRAP15: equ >FFE0 +(2) 0 : =FFDE VEC_TRAP16: equ >FFDE +(2) 0 : =FFDC VEC_TRAP17: equ >FFDC +(2) 0 : =FFDA VEC_TRAP18: equ >FFDA +(2) 0 : =FFD8 VEC_TRAP19: equ >FFD8 +(2) 0 : =FFD6 VEC_TRAP20: equ >FFD6 +(2) 0 : =FFD4 VEC_TRAP21: equ >FFD4 +(2) 0 : =FFD2 VEC_TRAP22: equ >FFD2 +(2) 0 : =FFD0 VEC_TRAP23: equ >FFD0 +(2) 0 : +(2) 0 : *** Internal Peripherals +(2) 0 : =100 IOCNT0: equ >0100 I/O Control register +(2) 0 : =20 INT3_F: equ ?100000 #INT3 flag +(2) 0 : =10 INT3_E: equ ?010000 #INT3 enable +(2) 0 : =8 INT2_F: equ ?001000 INT2 flag +(2) 0 : =4 INT2_E: equ ?000100 INT2 enable +(2) 0 : =2 INT1_F: equ ?000010 #INT1 flag +(2) 0 : =1 INT1_E: equ ?000001 #INT1 enable +(2) 0 : =102 T1DATA: equ >0102 Timer 1 data +(2) 0 : =103 T1CTL: equ >0103 Timer 1 control +(2) 0 : =104 APORT: equ >0104 Port A data +(2) 0 : =106 BPORT: equ >0106 Port B data +(2) 0 : =108 CPORT: equ >0108 Port C data +(2) 0 : =109 CDDR: equ >0109 Port C data direction register +(2) 0 : =10A DPORT: equ >010A Port D data +(2) 0 : =10B DDDR: equ >010B Port D data direction register +(2) 0 : +(2) 0 : *** Local Variables: +(2) 0 : *** comment-start: "*" +(2) 0 : *** End: +(1) 0 : *** TMS7001 +(1) 0 : *** Vector +(1) 0 : =FFF4 VEC_INT5: equ >FFF4 Tuner 2 +(1) 0 : =FFF6 VEC_INT4: equ >FFF6 Serial port +(1) 0 : *** Internal Peripherals +(1) 0 : =105 ADDR: equ >0105 Port A data direction register +(1) 0 : =110 IOCNT1: equ >0110 I/O control register 1 +(1) 0 : =8 INT5_F: equ ?1000 INT5 flag +(1) 0 : =4 INT5_E: equ ?0100 INT5 enable +(1) 0 : =2 INT4_F: equ ?0010 INT4 flag +(1) 0 : =1 INT4_E: equ ?0001 INT4 enable +(1) 0 : =111 SMODE: equ >0111 Serial mode (first write) +(1) 0 : =80 STOP_bm: equ ?10000000 1=2 stop bits. 0=1 stop bits +(1) 0 : =40 CMODE_bm: equ ?01000000 1=Communication mode, 0=Serial I/O mode +(1) 0 : =20 PEVEN_bm: equ ?00100000 1=Even parity, 0=Odd parity +(1) 0 : =10 PEN_bm: equ ?00010000 1=Parity enable, 0=Parity disable +(1) 0 : =C CHAR8_bm: equ ?00001100 3=8 bits/char +(1) 0 : =2 ASYNC_bm: equ ?00000010 1=Asynchronous, 0=Synchronous +(1) 0 : =1 MULTI_bm: equ ?00000001 1=Intel protocol, 0-Motorola protocol +(1) 0 : =111 SCTL0: equ >0111 Serial control 0 (write only) +(1) 0 : =40 UR_bm: equ ?01000000 1=Reset serial port +(1) 0 : =10 ER_bm: equ ?00010000 1=Reset error flags +(1) 0 : =4 RXEN_bm: equ ?00000100 1=Receiver enable, 0=A5 is GPIO +(1) 0 : =2 SCLKEN_bm: equ ?00000010 1=A4 is SCLK, 0=A4 is GPIO +(1) 0 : =1 TXEN_bm: equ ?00000001 1=Transmitter enable, 0=Transmitter disable +(1) 0 : =111 SSTAT: equ >0111 Serial status register (read only) +(1) 0 : =40 BFKDR_bm: equ ?01000000 1=Break detect +(1) 0 : =20 FE_bm: equ ?00100000 1=Framing error +(1) 0 : =10 OE_bm: equ ?00010000 1=Overrun error +(1) 0 : =8 PE_bm: equ ?00001000 1=Parity error +(1) 0 : =4 TXE_bm: equ ?00000100 1=Transmitter empty +(1) 0 : =2 RXRDY_bm: equ ?00000010 1=RXBUF ready with new character +(1) 0 : =1 TXRDY_bm: equ ?00000001 1=TXBYF ready for character +(1) 0 : =112 T2DATA: equ >0112 Timer 2 data +(1) 0 : =113 T2CNTL: equ >0113 Timer 2 control +(1) 0 : =114 T3DATA: equ >0114 Timer 3 data +(1) 0 : =115 SCTL1: equ >0115 Serial control +(1) 0 : =40 CLK_bm: equ ?01000000 1=Internal SCLK from Timer3, 0=SCLK +(1) 0 : =4 T3ENB_bm: equ ?00000100 1=Enable T3 to set INT4 flag +(1) 0 : =3 PRE3_bm: equ ?00000011 Prescaler reload reg PR +(1) 0 : =116 RXBUF: equ >0116 Receive buffer +(1) 0 : =117 TXBUF: equ >0117 Transmitter buffer +(1) 0 : +(1) 0 : *** Local Variables: +(1) 0 : *** comment-start: "*" +(1) 0 : *** End: + 0 : + FFFE : org VEC_RESET + FFFE : 10 00 data initialize + 10000 : + 1000 : org >1000 + 1000 : initialize: + 1000 : A4 08 06 orp %?1000, BPORT Pass through TXD (PB3=1) + 1003 : A2 00 11 movp %0, SMODE Select SCTL0 + 1006 : A2 40 11 movp %UR_bm, SCTL0 Select SMODE by reset + 1009 : A2 4E 11 movp %CMODE_bm|CHAR8_bm|ASYNC_bm, SMODE 8 bits asynchronous + 100C : A2 05 11 movp %RXEN_bm|TXEN_bm, SCTL0 Rx/Tx enable + 100F : A2 0C 14 movp %12, T3DATA 9600 bps (TR) + 1012 : A2 40 15 movp %CLK_bm, SCTL1 Enable internal clock, PR=0 + 1015 : + 1015 : 8E 10 27 loop: call @getchar + 1018 : B0 tsta + 1019 : E2 0B jeq halt_to_system + 101B : 8E 10 2E echo: call @putchar + 101E : 2D 0D cmp %>0D, A + 1020 : E6 F3 jne loop + 1022 : 22 0A mov %>0A, A + 1024 : E0 F5 jmp echo + 1026 : halt_to_system: + 1026 : 01 idle + 1027 : + 1027 : getchar: + 1027 : A7 02 11 FC btjzp %RXRDY_bm, SSTAT, getchar + 102B : 80 16 movp RXBUF, A + 102D : 0A rets + 102E : + 102E : putchar: + 102E : A7 01 11 FC btjzp %TXRDY_bm, SSTAT, putchar + 1032 : 82 17 movp A, TXBUF + 1034 : 0A rets + 1035 : + 1035 : *** Local Variables: + 1035 : *** mode: asm + 1035 : *** mode: flyspell-prog + 1035 : *** comment-start: "*" + 1035 : *** End: diff --git a/samples/tms7000/serialir.asm b/samples/tms7000/serialir.asm new file mode 100644 index 00000000..f3be99b3 --- /dev/null +++ b/samples/tms7000/serialir.asm @@ -0,0 +1,74 @@ +;;; -*- mode: asm; mode: flyspell-prog; -*- + cpu tms7000 + include "tms7001.inc" + + org >2000 +rx_queue_size: equ 128 +rx_queue: bss rx_queue_size + + * Internal registers + org >60 + * TMS7000's SP is pre-increment/post-decrement +stack: + + org VEC_INT4 + data isr_int4 + + org VEC_RESET + data initialize + + org >1000 +initialize: + mov %stack, B + ldsp + movd %rx_queue, R3 + mov %rx_queue_size, B + call @queue_init + ** initialize Serial + orp %?1000, BPORT Pass through TXD (PB3=1) + movp %0, SMODE Select SCTL0 + movp %UR_bm, SCTL0 Select SMODE by reset + movp %CMODE_bm|CHAR8_bm|ASYNC_bm, SMODE 8 bits asynchronous + movp %RXEN_bm|TXEN_bm, SCTL0 Rx/Tx enable + movp %12, T3DATA 9600 bps (TR) + movp %CLK_bm, SCTL1 Enable internal clock, PR=0 + movp %INT4_E|INT4_F, IOCNT1 clear/enable INT4 + +loop: + eint + movd %rx_queue, R3 + dint (clear all ST bits) + call @queue_remove + jnc loop + eint + tsta + jz halt_to_system + call @putchar + cmp %>0D, A + jne loop + mov %>0A, A + call @putchar + jmp loop +halt_to_system: + idle + +putchar: + btjzp %TXRDY_bm, SSTAT, putchar + movp A, TXBUF + rets + + include "queue.inc" + +isr_int4: + btjzp %RXRDY_bm, SSTAT, isr_int4_return + push A + movp RXBUF, A + push R2 + push R3 + movd %rx_queue, R3 + call @queue_add + pop R3 + pop R2 + pop A +isr_int4_return: + reti diff --git a/samples/tms7000/serialir.hex b/samples/tms7000/serialir.hex new file mode 100644 index 00000000..88bd9f93 --- /dev/null +++ b/samples/tms7000/serialir.hex @@ -0,0 +1,10 @@ +:2010000052600D8820000352808E1049A40806A20011A24011A24E11A20511A20C14A240F8 +:2010200015A203100588200003068E1094E7F505B0E20E8E10422D0DE6EA220A8E1042E0A7 +:20104000E301A70111FC82170AB59B03622A04D3039B035A02D303B59B03D303CAFA0AB81C +:201060009A03D3039D03E702B90AB3D2039B03B9780203D803B89A032802480003B99B0359 +:20108000D903B89A03B3D2039D03E701B5D3039B03B9070A9A03E602B00AB29B037803030F +:2010A000D8039A0328014800039A03D903B89A03B37A02039D03E701B57802039B03B9072C +:1910C0000AA7021113B88016D802D803882000038E105FD903D902B90B1A +:02FFF60010C138 +:02FFFE001000F1 +:00000001FF diff --git a/samples/tms7000/serialir.lst b/samples/tms7000/serialir.lst new file mode 100644 index 00000000..2250f7f4 --- /dev/null +++ b/samples/tms7000/serialir.lst @@ -0,0 +1,281 @@ + 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- + 0 : cpu tms7000 + 0 : include "tms7001.inc" +(1) 0 : *** -*- mode: asm; mode: flyspell-prog; -*- +(1) 0 : include "tms7000.inc" +(2) 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(2) 0 : *** TMS7000 +(2) 0 : *** Status Register +(2) 0 : =80 ST_CARRY: equ ?10000000 set to 1 if carry occurred +(2) 0 : =40 ST_NEGATIVE: equ ?01000000 set to 1 if result is negative +(2) 0 : =20 ST_ZERO: equ ?00100000 set to 1 if result is zero +(2) 0 : =10 ST_INT: equ ?00010000 if 1, interrupt is enabled +(2) 0 : *** Vector +(2) 0 : =FFF8 VEC_INT3: equ >FFF8 #INT3 interrupt +(2) 0 : =FFFA VEC_INT2: equ >FFFA Timer 1 +(2) 0 : =FFFC VEC_INT1: equ >FFFC #INT1 interrupt +(2) 0 : =FFFE VEC_RESET: equ >FFFE #RESET vector +(2) 0 : *** Trap Vector +(2) 0 : =FFFE VEC_TRAP0: equ VEC_RESET +(2) 0 : =FFFC VEC_TRAP1: equ VEC_INT1 +(2) 0 : =FFFA VEC_TRAP2: equ VEC_INT2 +(2) 0 : =FFF8 VEC_TRAP3: equ VEC_INT3 +(2) 0 : =FFF6 VEC_TRAP4: equ >FFF6 +(2) 0 : =FFF4 VEC_TRAP5: equ >FFF4 +(2) 0 : =FFF2 VEC_TRAP6: equ >FFF2 +(2) 0 : =FFF0 VEC_TRAP7: equ >FFF0 +(2) 0 : =FFEE VEC_TRAP8: equ >FFEE +(2) 0 : =FFEC VEC_TRAP9: equ >FFEC +(2) 0 : =FFEA VEC_TRAP10: equ >FFEA +(2) 0 : =FFE8 VEC_TRAP11: equ >FFE8 +(2) 0 : =FFE6 VEC_TRAP12: equ >FFE6 +(2) 0 : =FFE4 VEC_TRAP13: equ >FFE4 +(2) 0 : =FFE2 VEC_TRAP14: equ >FFE2 +(2) 0 : =FFE0 VEC_TRAP15: equ >FFE0 +(2) 0 : =FFDE VEC_TRAP16: equ >FFDE +(2) 0 : =FFDC VEC_TRAP17: equ >FFDC +(2) 0 : =FFDA VEC_TRAP18: equ >FFDA +(2) 0 : =FFD8 VEC_TRAP19: equ >FFD8 +(2) 0 : =FFD6 VEC_TRAP20: equ >FFD6 +(2) 0 : =FFD4 VEC_TRAP21: equ >FFD4 +(2) 0 : =FFD2 VEC_TRAP22: equ >FFD2 +(2) 0 : =FFD0 VEC_TRAP23: equ >FFD0 +(2) 0 : +(2) 0 : *** Internal Peripherals +(2) 0 : =100 IOCNT0: equ >0100 I/O Control register +(2) 0 : =20 INT3_F: equ ?100000 #INT3 flag +(2) 0 : =10 INT3_E: equ ?010000 #INT3 enable +(2) 0 : =8 INT2_F: equ ?001000 INT2 flag +(2) 0 : =4 INT2_E: equ ?000100 INT2 enable +(2) 0 : =2 INT1_F: equ ?000010 #INT1 flag +(2) 0 : =1 INT1_E: equ ?000001 #INT1 enable +(2) 0 : =102 T1DATA: equ >0102 Timer 1 data +(2) 0 : =103 T1CTL: equ >0103 Timer 1 control +(2) 0 : =104 APORT: equ >0104 Port A data +(2) 0 : =106 BPORT: equ >0106 Port B data +(2) 0 : =108 CPORT: equ >0108 Port C data +(2) 0 : =109 CDDR: equ >0109 Port C data direction register +(2) 0 : =10A DPORT: equ >010A Port D data +(2) 0 : =10B DDDR: equ >010B Port D data direction register +(2) 0 : +(2) 0 : *** Local Variables: +(2) 0 : *** comment-start: "*" +(2) 0 : *** End: +(1) 0 : *** TMS7001 +(1) 0 : *** Vector +(1) 0 : =FFF4 VEC_INT5: equ >FFF4 Tuner 2 +(1) 0 : =FFF6 VEC_INT4: equ >FFF6 Serial port +(1) 0 : *** Internal Peripherals +(1) 0 : =105 ADDR: equ >0105 Port A data direction register +(1) 0 : =110 IOCNT1: equ >0110 I/O control register 1 +(1) 0 : =8 INT5_F: equ ?1000 INT5 flag +(1) 0 : =4 INT5_E: equ ?0100 INT5 enable +(1) 0 : =2 INT4_F: equ ?0010 INT4 flag +(1) 0 : =1 INT4_E: equ ?0001 INT4 enable +(1) 0 : =111 SMODE: equ >0111 Serial mode (first write) +(1) 0 : =80 STOP_bm: equ ?10000000 1=2 stop bits. 0=1 stop bits +(1) 0 : =40 CMODE_bm: equ ?01000000 1=Communication mode, 0=Serial I/O mode +(1) 0 : =20 PEVEN_bm: equ ?00100000 1=Even parity, 0=Odd parity +(1) 0 : =10 PEN_bm: equ ?00010000 1=Parity enable, 0=Parity disable +(1) 0 : =C CHAR8_bm: equ ?00001100 3=8 bits/char +(1) 0 : =2 ASYNC_bm: equ ?00000010 1=Asynchronous, 0=Synchronous +(1) 0 : =1 MULTI_bm: equ ?00000001 1=Intel protocol, 0-Motorola protocol +(1) 0 : =111 SCTL0: equ >0111 Serial control 0 (write only) +(1) 0 : =40 UR_bm: equ ?01000000 1=Reset serial port +(1) 0 : =10 ER_bm: equ ?00010000 1=Reset error flags +(1) 0 : =4 RXEN_bm: equ ?00000100 1=Receiver enable, 0=A5 is GPIO +(1) 0 : =2 SCLKEN_bm: equ ?00000010 1=A4 is SCLK, 0=A4 is GPIO +(1) 0 : =1 TXEN_bm: equ ?00000001 1=Transmitter enable, 0=Transmitter disable +(1) 0 : =111 SSTAT: equ >0111 Serial status register (read only) +(1) 0 : =40 BFKDR_bm: equ ?01000000 1=Break detect +(1) 0 : =20 FE_bm: equ ?00100000 1=Framing error +(1) 0 : =10 OE_bm: equ ?00010000 1=Overrun error +(1) 0 : =8 PE_bm: equ ?00001000 1=Parity error +(1) 0 : =4 TXE_bm: equ ?00000100 1=Transmitter empty +(1) 0 : =2 RXRDY_bm: equ ?00000010 1=RXBUF ready with new character +(1) 0 : =1 TXRDY_bm: equ ?00000001 1=TXBYF ready for character +(1) 0 : =112 T2DATA: equ >0112 Timer 2 data +(1) 0 : =113 T2CNTL: equ >0113 Timer 2 control +(1) 0 : =114 T3DATA: equ >0114 Timer 3 data +(1) 0 : =115 SCTL1: equ >0115 Serial control +(1) 0 : =40 CLK_bm: equ ?01000000 1=Internal SCLK from Timer3, 0=SCLK +(1) 0 : =4 T3ENB_bm: equ ?00000100 1=Enable T3 to set INT4 flag +(1) 0 : =3 PRE3_bm: equ ?00000011 Prescaler reload reg PR +(1) 0 : =116 RXBUF: equ >0116 Receive buffer +(1) 0 : =117 TXBUF: equ >0117 Transmitter buffer +(1) 0 : +(1) 0 : *** Local Variables: +(1) 0 : *** comment-start: "*" +(1) 0 : *** End: + 0 : + 2000 : org >2000 + 2000 : =80 rx_queue_size: equ 128 + 2000 : rx_queue: bss rx_queue_size + 2080 : + 2080 : * Internal registers + 60 : org >60 + 60 : * TMS7000's SP is pre-increment/post-decrement + 60 : stack: + 60 : + FFF6 : org VEC_INT4 + FFF6 : 10 C1 data isr_int4 + FFF8 : + FFFE : org VEC_RESET + FFFE : 10 00 data initialize + 10000 : + 1000 : org >1000 + 1000 : initialize: + 1000 : 52 60 mov %stack, B + 1002 : 0D ldsp + 1003 : 88 20 00 03 movd %rx_queue, R3 + 1007 : 52 80 mov %rx_queue_size, B + 1009 : 8E 10 49 call @queue_init + 100C : ** initialize Serial + 100C : A4 08 06 orp %?1000, BPORT Pass through TXD (PB3=1) + 100F : A2 00 11 movp %0, SMODE Select SCTL0 + 1012 : A2 40 11 movp %UR_bm, SCTL0 Select SMODE by reset + 1015 : A2 4E 11 movp %CMODE_bm|CHAR8_bm|ASYNC_bm, SMODE 8 bits asynchronous + 1018 : A2 05 11 movp %RXEN_bm|TXEN_bm, SCTL0 Rx/Tx enable + 101B : A2 0C 14 movp %12, T3DATA 9600 bps (TR) + 101E : A2 40 15 movp %CLK_bm, SCTL1 Enable internal clock, PR=0 + 1021 : A2 03 10 movp %INT4_E|INT4_F, IOCNT1 clear/enable INT4 + 1024 : + 1024 : loop: + 1024 : 05 eint + 1025 : 88 20 00 03 movd %rx_queue, R3 + 1029 : 06 dint (clear all ST bits) + 102A : 8E 10 94 call @queue_remove + 102D : E7 F5 jnc loop + 102F : 05 eint + 1030 : B0 tsta + 1031 : E2 0E jz halt_to_system + 1033 : 8E 10 42 call @putchar + 1036 : 2D 0D cmp %>0D, A + 1038 : E6 EA jne loop + 103A : 22 0A mov %>0A, A + 103C : 8E 10 42 call @putchar + 103F : E0 E3 jmp loop + 1041 : halt_to_system: + 1041 : 01 idle + 1042 : + 1042 : putchar: + 1042 : A7 01 11 FC btjzp %TXRDY_bm, SSTAT, putchar + 1046 : 82 17 movp A, TXBUF + 1048 : 0A rets + 1049 : + 1049 : include "queue.inc" +(1) 1049 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 1049 : *** [queue] queue structure +(1) 1049 : =0 queue_len: equ 0 queue length +(1) 1049 : =1 queue_size: equ 1 buffer size +(1) 1049 : =2 queue_put: equ 2 queue put index +(1) 1049 : =3 queue_get: equ 3 queue get index +(1) 1049 : =4 queue_buf: equ 4 buffer start offset +(1) 1049 : +(1) 1049 : *** [queue] Initialize queue +(1) 1049 : *** @param R2:R3 queue work space pointer +(1) 1049 : *** @param B queue work space size +(1) 1049 : *** @clobber A B R2:R3 +(1) 1049 : queue_init: +(1) 1049 : B5 clr A +(1) 104A : 9B 03 sta *R3 queue_len +(1) 104C : 62 mov B, A +(1) 104D : 2A 04 sub %queue_buf, A +(1) 104F : D3 03 inc R3 +(1) 1051 : 9B 03 sta *R3 queue_size +(1) 1053 : 5A 02 sub %queue_put, B offset queue_len and queue_size +(1) 1055 : D3 03 inc R3 R2:R3=&queue_put +(1) 1057 : B5 clr A +(1) 1058 : queue_init_loop: +(1) 1058 : 9B 03 sta *R3 +(1) 105A : D3 03 inc R3 +(1) 105C : CA FA djnz B, queue_init_loop +(1) 105E : 0A rets +(1) 105F : +(1) 105F : *** [queue] Add an element to queue +(1) 105F : *** @param R2:R3 queue work space pointer +(1) 105F : *** @param A an element +(1) 105F : *** @return ST.C 0 if queue is full +(1) 105F : *** @clobber R2:R3 +(1) 105F : queue_add: +(1) 105F : B8 push A +(1) 1060 : 9A 03 lda *R3 A=queue_len +(1) 1062 : D3 03 inc R3 R2:R3=&queue_size +(1) 1064 : 9D 03 cmpa *R3 +(1) 1066 : E7 02 jl queue_add_element +(1) 1068 : B9 pop A ST.C=0 +(1) 1069 : 0A rets +(1) 106A : queue_add_element: +(1) 106A : B3 inc A +(1) 106B : D2 03 dec R3 +(1) 106D : 9B 03 sta *R3 queue_len++ +(1) 106F : B9 pop A +(1) 1070 : 78 02 03 add %queue_put-queue_len, R3 R2:R3=&queue_put +(1) 1073 : D8 03 push R3 +(1) 1075 : B8 push A +(1) 1076 : 9A 03 lda *R3 A=queue_put +(1) 1078 : 28 02 add %queue_buf-queue_put, A +(1) 107A : 48 00 03 add A, R3 R2:R3=&queue[queue_put] +(1) 107D : B9 pop A +(1) 107E : 9B 03 sta *R3 store element +(1) 1080 : D9 03 pop R3 R2:R3=&queue_put +(1) 1082 : B8 push A +(1) 1083 : 9A 03 lda *R3 +(1) 1085 : B3 inc A +(1) 1086 : D2 03 dec R3 R2:R3=&queue_size +(1) 1088 : 9D 03 cmpa *R3 +(1) 108A : E7 01 jl queue_add_return +(1) 108C : B5 clr A wraparound +(1) 108D : queue_add_return: +(1) 108D : D3 03 inc R3 R2:R3=&queue_put +(1) 108F : 9B 03 sta *R3 update queue_put +(1) 1091 : B9 pop A +(1) 1092 : 07 setc ST.C=1 +(1) 1093 : 0A rets +(1) 1094 : +(1) 1094 : *** [queue] Remove an element from queue +(1) 1094 : *** @param R2:R3 queue work space pointer +(1) 1094 : *** @return A an element +(1) 1094 : *** @return ST.C 0 if queue is empty +(1) 1094 : queue_remove: +(1) 1094 : 9A 03 lda *R3 A=queue_len +(1) 1096 : E6 02 jnz queue_remove_elem +(1) 1098 : B0 clrc +(1) 1099 : 0A rets +(1) 109A : queue_remove_elem: +(1) 109A : B2 dec A +(1) 109B : 9B 03 sta *R3 queue_len-- +(1) 109D : 78 03 03 add %queue_get-queue_len, R3 R2:R3=&queue_get +(1) 10A0 : D8 03 push R3 +(1) 10A2 : 9A 03 lda *R3 A=queue_get +(1) 10A4 : 28 01 add %queue_buf-queue_get, A +(1) 10A6 : 48 00 03 add A, R3 R2:R3=&queue_buf[queue_get] +(1) 10A9 : 9A 03 lda *R3 remove element +(1) 10AB : D9 03 pop R3 R2:R3=&queue_get +(1) 10AD : B8 push A +(1) 10AE : 9A 03 lda *R3 +(1) 10B0 : B3 inc A +(1) 10B1 : 7A 02 03 sub %queue_get-queue_size, R3 +(1) 10B4 : 9D 03 cmpa *R3 +(1) 10B6 : E7 01 jl queue_remove_return +(1) 10B8 : B5 clr A wraparound +(1) 10B9 : queue_remove_return: +(1) 10B9 : 78 02 03 add %queue_get-queue_size, R3 +(1) 10BC : 9B 03 sta *R3 update queue_get +(1) 10BE : B9 pop A +(1) 10BF : 07 setc +(1) 10C0 : 0A rets + 10C1 : + 10C1 : isr_int4: + 10C1 : A7 02 11 13 btjzp %RXRDY_bm, SSTAT, isr_int4_return + 10C5 : B8 push A + 10C6 : 80 16 movp RXBUF, A + 10C8 : D8 02 push R2 + 10CA : D8 03 push R3 + 10CC : 88 20 00 03 movd %rx_queue, R3 + 10D0 : 8E 10 5F call @queue_add + 10D3 : D9 03 pop R3 + 10D5 : D9 02 pop R2 + 10D7 : B9 pop A + 10D8 : isr_int4_return: + 10D8 : 0B reti diff --git a/samples/tms7000/serialitr.asm b/samples/tms7000/serialitr.asm new file mode 100644 index 00000000..3e7413db --- /dev/null +++ b/samples/tms7000/serialitr.asm @@ -0,0 +1,173 @@ +;;; -*- mode: asm; mode: flyspell-prog; -*- + cpu tms7000 + include "tms7001.inc" + + org >2000 +rx_queue_size: equ 128 +rx_queue: bss rx_queue_size +tx_queue_size: equ 128 +tx_queue: bss tx_queue_size + + * Internal registers + org >10 +tx_enable: bss 1 + * TMS7000's SP is pre-increment/post-decrement +stack: + + org VEC_INT4 + data isr_int4 + + org VEC_RESET + data initialize + + org >1000 +initialize: + mov %stack, B + ldsp + movd %rx_queue, R3 + mov %rx_queue_size, B + call @queue_init + movd %tx_queue, R3 + mov %tx_queue_size, B + call @queue_init + ** initialize Serial + orp %?1000, BPORT Pass through TXD (PB3=1) + movp %0, SMODE Select SCTL0 + movp %UR_bm, SCTL0 Select SMODE by reset + movp %CMODE_bm|CHAR8_bm|ASYNC_bm, SMODE 8 bits asynchronous + clr tx_enable Tx disable + movp %RXEN_bm, SCTL0 Rx enable + movp %12, T3DATA 9600 bps (TR) + movp %CLK_bm, SCTL1 Enable internal clock, PR=0 + movp %INT4_F|INT4_E, IOCNT1 clear/enable INT4 + +loop: + call @getchar + jnc loop + tsta + jz halt_to_system + mov A, B + call @putchar echo + call @putspace + call @put_hex8 print in hex + call @putspace + call @put_bin8 print in binary + call @newline + jmp loop +halt_to_system: + idle + + *** Put sapce + *** @clobber A +putspace: + mov %' ', A + jmp putchar + + *** Put newline + *** @clobber A +newline: + mov %>0D, A + call @putchar + mov %>0A, A + jmp putchar + + *** Print uint8_t in hex + *** @param B uint8_t value to be printed in hex. + *** @clobber A +put_hex8: + mov %'0', A + call @putchar + mov %'x', A + call @putchar + mov B, A + swap A + call @put_hex4 + mov B, A +put_hex4: + and %>0F, A + cmp %10, A + jl put_hex8_dec + add %'A'-10-'0', A +put_hex8_dec: + add %'0', A + jmp putchar + + *** Print uint8_t in binary + *** @param B uint8_t value to be printed in binary. + *** @clobber A B +put_bin8: + mov %'0', A + call @putchar + mov %'b', A + call @putchar + call @put_bin4 +put_bin4: + call @put_bin2 +put_bin2: + call @put_bin1 +put_bin1: + mov %'0', A + rlc B + jnc putchar ; MSB=0 + inc A ; MSB=1 + jmp putchar + + *** Get character + *** @return A + *** @return ST.C 0 if no character + *** @clobber R2:R3 +getchar: + movd %rx_queue, R3 + dint + call @queue_remove + jnc getchar_empty + eint ST.C=1 + rets +getchar_empty: + eint ST.C=1 + clrc + rets + + *** Put character + *** @param A + *** @clobber R2:R3 +putchar: + btjo %1, tx_enable, putchar_add + or %1, tx_enable enable Tx + movp %RXEN_bm|TXEN_bm, SCTL0 + movp A, TXBUF + rets +putchar_add: + eint + movd %tx_queue, R3 + dint + call @queue_add + jnc putchar_add + eint + rets + + include "queue.inc" + +isr_int4: + push A + push R2 + push R3 + btjzp %RXRDY_bm, SSTAT, isr_tx + movp RXBUF, A + movd %rx_queue, R3 + call @queue_add +isr_tx: + btjzp %TXRDY_bm, SSTAT, isr_int4_exit + movd %tx_queue, R3 + call @queue_remove + jnc isr_tx_empty + movp A, TXBUF send character +isr_int4_exit: + pop R3 + pop R2 + pop A + reti +isr_tx_empty: + clr tx_enable disable Tx + movp %RXEN_bm, SCTL0 + jmp isr_int4_exit diff --git a/samples/tms7000/serialitr.hex b/samples/tms7000/serialitr.hex new file mode 100644 index 00000000..4c91a718 --- /dev/null +++ b/samples/tms7000/serialitr.hex @@ -0,0 +1,14 @@ +:2010000052110D8820000352808E10BA8820800352808E10BAA40806A20011A24011A24EEE +:2010200011D510A20411A20C14A24015A203108E1091E7FBB0E215C08E10A08E104D8E1056 +:201040005A8E104D8E10768E1051E0E3012220E04F220D8E10A0220AE04622308E10A022A2 +:20106000788E10A062B78E106A62230F2D0AE70228072830E02A22308E10A022628E10A002 +:201080008E10838E10868E10892230CFE712B3E00F88200003068E1105E702050A05B00A1C +:2010A00076011009740110A2051182170A0588208003068E10D0E7F5050AB59B03622A044E +:2010C000D3039B035A02D303B59B03D303CAFA0AB89A03D3039D03E702B90AB3D2039B03D6 +:2010E000B9780203D803B89A032802480003B99B03D903B89A03B3D2039D03E701B5D303F2 +:201100009B03B9070A9A03E602B00AB29B03780303D8039A0328014800039A03D903B89AA3 +:2011200003B37A02039D03E701B57802039B03B9070AB8D802D803A70211098016882000EA +:20114000038E10D0A701110B882080038E1105E7088217D903D902B90BD510A20411E0F319 +:02FFF6001132C6 +:02FFFE001000F1 +:00000001FF diff --git a/samples/tms7000/serialitr.lst b/samples/tms7000/serialitr.lst new file mode 100644 index 00000000..0cf99d4c --- /dev/null +++ b/samples/tms7000/serialitr.lst @@ -0,0 +1,380 @@ + 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- + 0 : cpu tms7000 + 0 : include "tms7001.inc" +(1) 0 : *** -*- mode: asm; mode: flyspell-prog; -*- +(1) 0 : include "tms7000.inc" +(2) 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(2) 0 : *** TMS7000 +(2) 0 : *** Status Register +(2) 0 : =80 ST_CARRY: equ ?10000000 set to 1 if carry occurred +(2) 0 : =40 ST_NEGATIVE: equ ?01000000 set to 1 if result is negative +(2) 0 : =20 ST_ZERO: equ ?00100000 set to 1 if result is zero +(2) 0 : =10 ST_INT: equ ?00010000 if 1, interrupt is enabled +(2) 0 : *** Vector +(2) 0 : =FFF8 VEC_INT3: equ >FFF8 #INT3 interrupt +(2) 0 : =FFFA VEC_INT2: equ >FFFA Timer 1 +(2) 0 : =FFFC VEC_INT1: equ >FFFC #INT1 interrupt +(2) 0 : =FFFE VEC_RESET: equ >FFFE #RESET vector +(2) 0 : *** Trap Vector +(2) 0 : =FFFE VEC_TRAP0: equ VEC_RESET +(2) 0 : =FFFC VEC_TRAP1: equ VEC_INT1 +(2) 0 : =FFFA VEC_TRAP2: equ VEC_INT2 +(2) 0 : =FFF8 VEC_TRAP3: equ VEC_INT3 +(2) 0 : =FFF6 VEC_TRAP4: equ >FFF6 +(2) 0 : =FFF4 VEC_TRAP5: equ >FFF4 +(2) 0 : =FFF2 VEC_TRAP6: equ >FFF2 +(2) 0 : =FFF0 VEC_TRAP7: equ >FFF0 +(2) 0 : =FFEE VEC_TRAP8: equ >FFEE +(2) 0 : =FFEC VEC_TRAP9: equ >FFEC +(2) 0 : =FFEA VEC_TRAP10: equ >FFEA +(2) 0 : =FFE8 VEC_TRAP11: equ >FFE8 +(2) 0 : =FFE6 VEC_TRAP12: equ >FFE6 +(2) 0 : =FFE4 VEC_TRAP13: equ >FFE4 +(2) 0 : =FFE2 VEC_TRAP14: equ >FFE2 +(2) 0 : =FFE0 VEC_TRAP15: equ >FFE0 +(2) 0 : =FFDE VEC_TRAP16: equ >FFDE +(2) 0 : =FFDC VEC_TRAP17: equ >FFDC +(2) 0 : =FFDA VEC_TRAP18: equ >FFDA +(2) 0 : =FFD8 VEC_TRAP19: equ >FFD8 +(2) 0 : =FFD6 VEC_TRAP20: equ >FFD6 +(2) 0 : =FFD4 VEC_TRAP21: equ >FFD4 +(2) 0 : =FFD2 VEC_TRAP22: equ >FFD2 +(2) 0 : =FFD0 VEC_TRAP23: equ >FFD0 +(2) 0 : +(2) 0 : *** Internal Peripherals +(2) 0 : =100 IOCNT0: equ >0100 I/O Control register +(2) 0 : =20 INT3_F: equ ?100000 #INT3 flag +(2) 0 : =10 INT3_E: equ ?010000 #INT3 enable +(2) 0 : =8 INT2_F: equ ?001000 INT2 flag +(2) 0 : =4 INT2_E: equ ?000100 INT2 enable +(2) 0 : =2 INT1_F: equ ?000010 #INT1 flag +(2) 0 : =1 INT1_E: equ ?000001 #INT1 enable +(2) 0 : =102 T1DATA: equ >0102 Timer 1 data +(2) 0 : =103 T1CTL: equ >0103 Timer 1 control +(2) 0 : =104 APORT: equ >0104 Port A data +(2) 0 : =106 BPORT: equ >0106 Port B data +(2) 0 : =108 CPORT: equ >0108 Port C data +(2) 0 : =109 CDDR: equ >0109 Port C data direction register +(2) 0 : =10A DPORT: equ >010A Port D data +(2) 0 : =10B DDDR: equ >010B Port D data direction register +(2) 0 : +(2) 0 : *** Local Variables: +(2) 0 : *** comment-start: "*" +(2) 0 : *** End: +(1) 0 : *** TMS7001 +(1) 0 : *** Vector +(1) 0 : =FFF4 VEC_INT5: equ >FFF4 Tuner 2 +(1) 0 : =FFF6 VEC_INT4: equ >FFF6 Serial port +(1) 0 : *** Internal Peripherals +(1) 0 : =105 ADDR: equ >0105 Port A data direction register +(1) 0 : =110 IOCNT1: equ >0110 I/O control register 1 +(1) 0 : =8 INT5_F: equ ?1000 INT5 flag +(1) 0 : =4 INT5_E: equ ?0100 INT5 enable +(1) 0 : =2 INT4_F: equ ?0010 INT4 flag +(1) 0 : =1 INT4_E: equ ?0001 INT4 enable +(1) 0 : =111 SMODE: equ >0111 Serial mode (first write) +(1) 0 : =80 STOP_bm: equ ?10000000 1=2 stop bits. 0=1 stop bits +(1) 0 : =40 CMODE_bm: equ ?01000000 1=Communication mode, 0=Serial I/O mode +(1) 0 : =20 PEVEN_bm: equ ?00100000 1=Even parity, 0=Odd parity +(1) 0 : =10 PEN_bm: equ ?00010000 1=Parity enable, 0=Parity disable +(1) 0 : =C CHAR8_bm: equ ?00001100 3=8 bits/char +(1) 0 : =2 ASYNC_bm: equ ?00000010 1=Asynchronous, 0=Synchronous +(1) 0 : =1 MULTI_bm: equ ?00000001 1=Intel protocol, 0-Motorola protocol +(1) 0 : =111 SCTL0: equ >0111 Serial control 0 (write only) +(1) 0 : =40 UR_bm: equ ?01000000 1=Reset serial port +(1) 0 : =10 ER_bm: equ ?00010000 1=Reset error flags +(1) 0 : =4 RXEN_bm: equ ?00000100 1=Receiver enable, 0=A5 is GPIO +(1) 0 : =2 SCLKEN_bm: equ ?00000010 1=A4 is SCLK, 0=A4 is GPIO +(1) 0 : =1 TXEN_bm: equ ?00000001 1=Transmitter enable, 0=Transmitter disable +(1) 0 : =111 SSTAT: equ >0111 Serial status register (read only) +(1) 0 : =40 BFKDR_bm: equ ?01000000 1=Break detect +(1) 0 : =20 FE_bm: equ ?00100000 1=Framing error +(1) 0 : =10 OE_bm: equ ?00010000 1=Overrun error +(1) 0 : =8 PE_bm: equ ?00001000 1=Parity error +(1) 0 : =4 TXE_bm: equ ?00000100 1=Transmitter empty +(1) 0 : =2 RXRDY_bm: equ ?00000010 1=RXBUF ready with new character +(1) 0 : =1 TXRDY_bm: equ ?00000001 1=TXBYF ready for character +(1) 0 : =112 T2DATA: equ >0112 Timer 2 data +(1) 0 : =113 T2CNTL: equ >0113 Timer 2 control +(1) 0 : =114 T3DATA: equ >0114 Timer 3 data +(1) 0 : =115 SCTL1: equ >0115 Serial control +(1) 0 : =40 CLK_bm: equ ?01000000 1=Internal SCLK from Timer3, 0=SCLK +(1) 0 : =4 T3ENB_bm: equ ?00000100 1=Enable T3 to set INT4 flag +(1) 0 : =3 PRE3_bm: equ ?00000011 Prescaler reload reg PR +(1) 0 : =116 RXBUF: equ >0116 Receive buffer +(1) 0 : =117 TXBUF: equ >0117 Transmitter buffer +(1) 0 : +(1) 0 : *** Local Variables: +(1) 0 : *** comment-start: "*" +(1) 0 : *** End: + 0 : + 2000 : org >2000 + 2000 : =80 rx_queue_size: equ 128 + 2000 : rx_queue: bss rx_queue_size + 2080 : =80 tx_queue_size: equ 128 + 2080 : tx_queue: bss tx_queue_size + 2100 : + 2100 : * Internal registers + 10 : org >10 + 10 : tx_enable: bss 1 + 11 : * TMS7000's SP is pre-increment/post-decrement + 11 : stack: + 11 : + FFF6 : org VEC_INT4 + FFF6 : 11 32 data isr_int4 + FFF8 : + FFFE : org VEC_RESET + FFFE : 10 00 data initialize + 10000 : + 1000 : org >1000 + 1000 : initialize: + 1000 : 52 11 mov %stack, B + 1002 : 0D ldsp + 1003 : 88 20 00 03 movd %rx_queue, R3 + 1007 : 52 80 mov %rx_queue_size, B + 1009 : 8E 10 BA call @queue_init + 100C : 88 20 80 03 movd %tx_queue, R3 + 1010 : 52 80 mov %tx_queue_size, B + 1012 : 8E 10 BA call @queue_init + 1015 : ** initialize Serial + 1015 : A4 08 06 orp %?1000, BPORT Pass through TXD (PB3=1) + 1018 : A2 00 11 movp %0, SMODE Select SCTL0 + 101B : A2 40 11 movp %UR_bm, SCTL0 Select SMODE by reset + 101E : A2 4E 11 movp %CMODE_bm|CHAR8_bm|ASYNC_bm, SMODE 8 bits asynchronous + 1021 : D5 10 clr tx_enable Tx disable + 1023 : A2 04 11 movp %RXEN_bm, SCTL0 Rx enable + 1026 : A2 0C 14 movp %12, T3DATA 9600 bps (TR) + 1029 : A2 40 15 movp %CLK_bm, SCTL1 Enable internal clock, PR=0 + 102C : A2 03 10 movp %INT4_F|INT4_E, IOCNT1 clear/enable INT4 + 102F : + 102F : loop: + 102F : 8E 10 91 call @getchar + 1032 : E7 FB jnc loop + 1034 : B0 tsta + 1035 : E2 15 jz halt_to_system + 1037 : C0 mov A, B + 1038 : 8E 10 A0 call @putchar echo + 103B : 8E 10 4D call @putspace + 103E : 8E 10 5A call @put_hex8 print in hex + 1041 : 8E 10 4D call @putspace + 1044 : 8E 10 76 call @put_bin8 print in binary + 1047 : 8E 10 51 call @newline + 104A : E0 E3 jmp loop + 104C : halt_to_system: + 104C : 01 idle + 104D : + 104D : *** Put sapce + 104D : *** @clobber A + 104D : putspace: + 104D : 22 20 mov %' ', A + 104F : E0 4F jmp putchar + 1051 : + 1051 : *** Put newline + 1051 : *** @clobber A + 1051 : newline: + 1051 : 22 0D mov %>0D, A + 1053 : 8E 10 A0 call @putchar + 1056 : 22 0A mov %>0A, A + 1058 : E0 46 jmp putchar + 105A : + 105A : *** Print uint8_t in hex + 105A : *** @param B uint8_t value to be printed in hex. + 105A : *** @clobber A + 105A : put_hex8: + 105A : 22 30 mov %'0', A + 105C : 8E 10 A0 call @putchar + 105F : 22 78 mov %'x', A + 1061 : 8E 10 A0 call @putchar + 1064 : 62 mov B, A + 1065 : B7 swap A + 1066 : 8E 10 6A call @put_hex4 + 1069 : 62 mov B, A + 106A : put_hex4: + 106A : 23 0F and %>0F, A + 106C : 2D 0A cmp %10, A + 106E : E7 02 jl put_hex8_dec + 1070 : 28 07 add %'A'-10-'0', A + 1072 : put_hex8_dec: + 1072 : 28 30 add %'0', A + 1074 : E0 2A jmp putchar + 1076 : + 1076 : *** Print uint8_t in binary + 1076 : *** @param B uint8_t value to be printed in binary. + 1076 : *** @clobber A B + 1076 : put_bin8: + 1076 : 22 30 mov %'0', A + 1078 : 8E 10 A0 call @putchar + 107B : 22 62 mov %'b', A + 107D : 8E 10 A0 call @putchar + 1080 : 8E 10 83 call @put_bin4 + 1083 : put_bin4: + 1083 : 8E 10 86 call @put_bin2 + 1086 : put_bin2: + 1086 : 8E 10 89 call @put_bin1 + 1089 : put_bin1: + 1089 : 22 30 mov %'0', A + 108B : CF rlc B + 108C : E7 12 jnc putchar ; MSB=0 + 108E : B3 inc A ; MSB=1 + 108F : E0 0F jmp putchar + 1091 : + 1091 : *** Get character + 1091 : *** @return A + 1091 : *** @return ST.C 0 if no character + 1091 : *** @clobber R2:R3 + 1091 : getchar: + 1091 : 88 20 00 03 movd %rx_queue, R3 + 1095 : 06 dint + 1096 : 8E 11 05 call @queue_remove + 1099 : E7 02 jnc getchar_empty + 109B : 05 eint ST.C=1 + 109C : 0A rets + 109D : getchar_empty: + 109D : 05 eint ST.C=1 + 109E : B0 clrc + 109F : 0A rets + 10A0 : + 10A0 : *** Put character + 10A0 : *** @param A + 10A0 : *** @clobber R2:R3 + 10A0 : putchar: + 10A0 : 76 01 10 09 btjo %1, tx_enable, putchar_add + 10A4 : 74 01 10 or %1, tx_enable enable Tx + 10A7 : A2 05 11 movp %RXEN_bm|TXEN_bm, SCTL0 + 10AA : 82 17 movp A, TXBUF + 10AC : 0A rets + 10AD : putchar_add: + 10AD : 05 eint + 10AE : 88 20 80 03 movd %tx_queue, R3 + 10B2 : 06 dint + 10B3 : 8E 10 D0 call @queue_add + 10B6 : E7 F5 jnc putchar_add + 10B8 : 05 eint + 10B9 : 0A rets + 10BA : + 10BA : include "queue.inc" +(1) 10BA : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 10BA : *** [queue] queue structure +(1) 10BA : =0 queue_len: equ 0 queue length +(1) 10BA : =1 queue_size: equ 1 buffer size +(1) 10BA : =2 queue_put: equ 2 queue put index +(1) 10BA : =3 queue_get: equ 3 queue get index +(1) 10BA : =4 queue_buf: equ 4 buffer start offset +(1) 10BA : +(1) 10BA : *** [queue] Initialize queue +(1) 10BA : *** @param R2:R3 queue work space pointer +(1) 10BA : *** @param B queue work space size +(1) 10BA : *** @clobber A B R2:R3 +(1) 10BA : queue_init: +(1) 10BA : B5 clr A +(1) 10BB : 9B 03 sta *R3 queue_len +(1) 10BD : 62 mov B, A +(1) 10BE : 2A 04 sub %queue_buf, A +(1) 10C0 : D3 03 inc R3 +(1) 10C2 : 9B 03 sta *R3 queue_size +(1) 10C4 : 5A 02 sub %queue_put, B offset queue_len and queue_size +(1) 10C6 : D3 03 inc R3 R2:R3=&queue_put +(1) 10C8 : B5 clr A +(1) 10C9 : queue_init_loop: +(1) 10C9 : 9B 03 sta *R3 +(1) 10CB : D3 03 inc R3 +(1) 10CD : CA FA djnz B, queue_init_loop +(1) 10CF : 0A rets +(1) 10D0 : +(1) 10D0 : *** [queue] Add an element to queue +(1) 10D0 : *** @param R2:R3 queue work space pointer +(1) 10D0 : *** @param A an element +(1) 10D0 : *** @return ST.C 0 if queue is full +(1) 10D0 : *** @clobber R2:R3 +(1) 10D0 : queue_add: +(1) 10D0 : B8 push A +(1) 10D1 : 9A 03 lda *R3 A=queue_len +(1) 10D3 : D3 03 inc R3 R2:R3=&queue_size +(1) 10D5 : 9D 03 cmpa *R3 +(1) 10D7 : E7 02 jl queue_add_element +(1) 10D9 : B9 pop A ST.C=0 +(1) 10DA : 0A rets +(1) 10DB : queue_add_element: +(1) 10DB : B3 inc A +(1) 10DC : D2 03 dec R3 +(1) 10DE : 9B 03 sta *R3 queue_len++ +(1) 10E0 : B9 pop A +(1) 10E1 : 78 02 03 add %queue_put-queue_len, R3 R2:R3=&queue_put +(1) 10E4 : D8 03 push R3 +(1) 10E6 : B8 push A +(1) 10E7 : 9A 03 lda *R3 A=queue_put +(1) 10E9 : 28 02 add %queue_buf-queue_put, A +(1) 10EB : 48 00 03 add A, R3 R2:R3=&queue[queue_put] +(1) 10EE : B9 pop A +(1) 10EF : 9B 03 sta *R3 store element +(1) 10F1 : D9 03 pop R3 R2:R3=&queue_put +(1) 10F3 : B8 push A +(1) 10F4 : 9A 03 lda *R3 +(1) 10F6 : B3 inc A +(1) 10F7 : D2 03 dec R3 R2:R3=&queue_size +(1) 10F9 : 9D 03 cmpa *R3 +(1) 10FB : E7 01 jl queue_add_return +(1) 10FD : B5 clr A wraparound +(1) 10FE : queue_add_return: +(1) 10FE : D3 03 inc R3 R2:R3=&queue_put +(1) 1100 : 9B 03 sta *R3 update queue_put +(1) 1102 : B9 pop A +(1) 1103 : 07 setc ST.C=1 +(1) 1104 : 0A rets +(1) 1105 : +(1) 1105 : *** [queue] Remove an element from queue +(1) 1105 : *** @param R2:R3 queue work space pointer +(1) 1105 : *** @return A an element +(1) 1105 : *** @return ST.C 0 if queue is empty +(1) 1105 : queue_remove: +(1) 1105 : 9A 03 lda *R3 A=queue_len +(1) 1107 : E6 02 jnz queue_remove_elem +(1) 1109 : B0 clrc +(1) 110A : 0A rets +(1) 110B : queue_remove_elem: +(1) 110B : B2 dec A +(1) 110C : 9B 03 sta *R3 queue_len-- +(1) 110E : 78 03 03 add %queue_get-queue_len, R3 R2:R3=&queue_get +(1) 1111 : D8 03 push R3 +(1) 1113 : 9A 03 lda *R3 A=queue_get +(1) 1115 : 28 01 add %queue_buf-queue_get, A +(1) 1117 : 48 00 03 add A, R3 R2:R3=&queue_buf[queue_get] +(1) 111A : 9A 03 lda *R3 remove element +(1) 111C : D9 03 pop R3 R2:R3=&queue_get +(1) 111E : B8 push A +(1) 111F : 9A 03 lda *R3 +(1) 1121 : B3 inc A +(1) 1122 : 7A 02 03 sub %queue_get-queue_size, R3 +(1) 1125 : 9D 03 cmpa *R3 +(1) 1127 : E7 01 jl queue_remove_return +(1) 1129 : B5 clr A wraparound +(1) 112A : queue_remove_return: +(1) 112A : 78 02 03 add %queue_get-queue_size, R3 +(1) 112D : 9B 03 sta *R3 update queue_get +(1) 112F : B9 pop A +(1) 1130 : 07 setc +(1) 1131 : 0A rets + 1132 : + 1132 : isr_int4: + 1132 : B8 push A + 1133 : D8 02 push R2 + 1135 : D8 03 push R3 + 1137 : A7 02 11 09 btjzp %RXRDY_bm, SSTAT, isr_tx + 113B : 80 16 movp RXBUF, A + 113D : 88 20 00 03 movd %rx_queue, R3 + 1141 : 8E 10 D0 call @queue_add + 1144 : isr_tx: + 1144 : A7 01 11 0B btjzp %TXRDY_bm, SSTAT, isr_int4_exit + 1148 : 88 20 80 03 movd %tx_queue, R3 + 114C : 8E 11 05 call @queue_remove + 114F : E7 08 jnc isr_tx_empty + 1151 : 82 17 movp A, TXBUF send character + 1153 : isr_int4_exit: + 1153 : D9 03 pop R3 + 1155 : D9 02 pop R2 + 1157 : B9 pop A + 1158 : 0B reti + 1159 : isr_tx_empty: + 1159 : D5 10 clr tx_enable disable Tx + 115B : A2 04 11 movp %RXEN_bm, SCTL0 + 115E : E0 F3 jmp isr_int4_exit diff --git a/samples/tms7000/tms7001.inc b/samples/tms7000/tms7001.inc index 914fe407..46eb73d2 100644 --- a/samples/tms7000/tms7001.inc +++ b/samples/tms7000/tms7001.inc @@ -7,17 +7,39 @@ VEC_INT4: equ >FFF6 Serial port *** Internal Peripherals ADDR: equ >0105 Port A data direction register IOCNT1: equ >0110 I/O control register 1 -INT5_F: equ ?1000 INT5 flag -INT5_E: equ ?0100 INT5 enable -INT4_F: equ ?0010 INT4 flag -INT4_E: equ ?0001 INT4 enable +INT5_F: equ ?1000 INT5 flag +INT5_E: equ ?0100 INT5 enable +INT4_F: equ ?0010 INT4 flag +INT4_E: equ ?0001 INT4 enable SMODE: equ >0111 Serial mode (first write) +STOP_bm: equ ?10000000 1=2 stop bits. 0=1 stop bits +CMODE_bm: equ ?01000000 1=Communication mode, 0=Serial I/O mode +PEVEN_bm: equ ?00100000 1=Even parity, 0=Odd parity +PEN_bm: equ ?00010000 1=Parity enable, 0=Parity disable +CHAR8_bm: equ ?00001100 3=8 bits/char +ASYNC_bm: equ ?00000010 1=Asynchronous, 0=Synchronous +MULTI_bm: equ ?00000001 1=Intel protocol, 0-Motorola protocol SCTL0: equ >0111 Serial control 0 (write only) +UR_bm: equ ?01000000 1=Reset serial port +ER_bm: equ ?00010000 1=Reset error flags +RXEN_bm: equ ?00000100 1=Receiver enable, 0=A5 is GPIO +SCLKEN_bm: equ ?00000010 1=A4 is SCLK, 0=A4 is GPIO +TXEN_bm: equ ?00000001 1=Transmitter enable, 0=Transmitter disable SSTAT: equ >0111 Serial status register (read only) +BFKDR_bm: equ ?01000000 1=Break detect +FE_bm: equ ?00100000 1=Framing error +OE_bm: equ ?00010000 1=Overrun error +PE_bm: equ ?00001000 1=Parity error +TXE_bm: equ ?00000100 1=Transmitter empty +RXRDY_bm: equ ?00000010 1=RXBUF ready with new character +TXRDY_bm: equ ?00000001 1=TXBYF ready for character T2DATA: equ >0112 Timer 2 data T2CNTL: equ >0113 Timer 2 control T3DATA: equ >0114 Timer 3 data SCTL1: equ >0115 Serial control +CLK_bm: equ ?01000000 1=Internal SCLK from Timer3, 0=SCLK +T3ENB_bm: equ ?00000100 1=Enable T3 to set INT4 flag +PRE3_bm: equ ?00000011 Prescaler reload reg PR RXBUF: equ >0116 Receive buffer TXBUF: equ >0117 Transmitter buffer diff --git a/samples/tms7000/tms70c02.inc b/samples/tms7000/tms70c02.inc index a949477a..9224e403 100644 --- a/samples/tms7000/tms70c02.inc +++ b/samples/tms7000/tms70c02.inc @@ -1,13 +1,14 @@ *** -*- mode: asm; mode: flyspell-prog; -*- include "tms7001.inc" - *** TMS7002 + *** TMS70C02 *** Internal Peripherals IOCNT2: equ >0101 I/O control register 2 -INT3_EDGE: ?100000 #INT3 1=edge sense, 0=level sense -INT3_POL: ?010000 #INT3 polarity 1=high/raising, 0=low/falling -INT1_EDGE: ?000010 #INT1 1=edge sense, 0=level sense -INT1_POL: ?000001 #INT1 polarity 1=high/raising, 0=low/falling +INT3_EDGE: equ ?100000 #INT3 1=edge sense, 0=level sense +INT3_POL: equ ?010000 #INT3 polarity 1=high/raising, 0=low/falling +INT1_EDGE: equ ?000010 #INT1 1=edge sense, 0=level sense +INT1_POL: equ ?000001 #INT1 polarity 1=high/raising, 0=low/falling *** - SCTL1 has start/stop bit of Timer 3 +T3RUN_bm: equ ?10000000 1=Start Timer 3 *** - Serial baud-rate is doubled than TMS7001 *** - #INT1 and #INT3 can be level active *** - No /4 clock option