]> rtime.felk.cvut.cz Git - fpga/virtex2/uart.git/commitdiff
Software modification to work whit HW UART
authorVladimir Burian <buriavl2@fel.cvut.cz>
Fri, 4 Feb 2011 19:56:41 +0000 (20:56 +0100)
committerVladimir Burian <buriavl2@fel.cvut.cz>
Fri, 4 Feb 2011 19:56:41 +0000 (20:56 +0100)
Code si almost all rewritten.

software/README.txt [deleted file]
software/fll.h [deleted file]
software/fll.s [deleted file]
software/hardware.h
software/main.c
software/makefile
software/miniterm.py [deleted file]
software/swuart.h [deleted file]
software/swuart.s [deleted file]
software/uart.c [new file with mode: 0644]
software/uart.h [new file with mode: 0644]

diff --git a/software/README.txt b/software/README.txt
deleted file mode 100644 (file)
index 79c251c..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-what's this?
-------------
-it's a simple example project for the MSP430 series MCU and the GCC port
-of the mspgcc project. the project contains a makefile and uses assembler
-and C sources. this time it is a software UART with Timer_A.
-
-this example shows the following features:
- - Timer_A uart, full duplex
-    o same pins as BSL (P1.1 TX, P2.2 RX)
-    o it contains a reusable code
-
- - software FLL
-   the watch crystal is used as reference and the main clock
-   is adjusted to 1.536MHz on startup
-
- - use uprintf to print formated strings and do a printf
-   emulation that prints to the serial port.
-
- - the main loop is a simple line editor. when a return character
-   ('\r', usualy RETURN key) is received, it writes the received
-   characters from the buffer to the serial port.
-   connect a terminal at 9600,N,8,1 to try it out.
-
- - makefile
-    o compile and link
-    o include assembler files
-    o convert to intel hex format
-    o generate a listing with mixed C / assembly
-
-required hardware
------------------
-
- - a MSP430F1121 or larger device (any from the F1x series)
-   connect pins P1.1 (TX) and P2.2 (RX) through level converters
-   to a terminal. you can also use a BSL hardware, the same pins
-   are used.
- - watch crystal 32.768kHz
- - optionaly a LED on P2.5  (470 Ohms series resistor to GND)
-
-disclaimer
-----------
-this example is part of the mspgcc project http://mspgcc.sf.net
-see license.txt for details.
-
-chris
\ No newline at end of file
diff --git a/software/fll.h b/software/fll.h
deleted file mode 100644 (file)
index 6740ca8..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef FLL_H
-#define FLL_H
-
-void fllInit(void);             //do an FLL loop to adjust system frequency
-
-#endif //FLL_H
diff --git a/software/fll.s b/software/fll.s
deleted file mode 100644 (file)
index 49e02c2..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#include "hardware.h"
-.text
-.global fllInit                         ; SW FLL to init DCO/SMCLK -frequency
-        .type   fllInit, @function
-fllInit:
-        mov.b   #BCSCTL1_FLL, &BCSCTL1  ; Init basic clock control reg 1
-        mov.b   #BCSCTL2_FLL, &BCSCTL2  ; Init basic clock control reg 2
-        mov     #TACTL_FLL, &TACTL      ; SMCLK is TA-clock / Timer stopped
-        bis     #MC1, &TACTL            ; Start timer: Continuos Mode
-        mov     #CCTL2_FLL, &CCTL2      ; Init CCR2 and Clear capture flag
-
-.Lwait0:bit     #CCIFG, &CCTL2          ; Test/Wait for capture flag
-        jz      .Lwait0                 ; May be used with INT / LPM0 later ?
-        mov     &CCR2, r15              ; Store CCR2 init-value
-        bic     #CCIFG, &CCTL2          ; Clear capture flag
-.Lwait1:bit     #CCIFG, &CCTL2          ; Test/Wait for capture flag
-        jz      .Lwait1                 ; May be used with INT / LPM0 later ?
-        bic     #CCIFG, &CCTL2          ; Clear capture flag
-        mov.b   &BCSCTL1, r14           ; Store current Rsel value
-        bic.b   #0x0f8, r14             ; Mask for Rsel bits
-        mov.b   &DCOCTL, r13            ; Store current DCO value
-
-.LfllUP:cmp.b   #DCOCTL_MAX, r13        ; Needs Rsel to be increased ?
-        jne     .LfllDN                 ; No
-        cmp.b   #7, r14                 ; Is max Rsel already selected ?
-        jge     .LfllER                 ; Yes, Rsel can not be increased
-        inc.b   &BCSCTL1                ; Increase Rsel
-        jmp     .LfllRx                 ; Test DCO again
-
-.LfllDN:cmp.b   #DCOCTL_MIN, r13        ; Needs Rsel to be decreased ?
-        jne     .LfllCP                 ; No
-        cmp.b   #0, r14                 ; Is min Rsel already selected ?
-        jeq     .LfllER                 ; Yes, Rsel can not be increased
-        dec.b   &BCSCTL1                ; Decrease Rsel
-.LfllRx:mov.b   #60h, &DCOCTL           ; Center DCO (may be optimized later ?)
-        jmp     .Lwait0                 ; Test DCO again
-.LfllCP:
-        mov     &CCR2, r12              ; Read captured value
-        sub     r15, r12                ; Subtract last captured value
-        mov     &CCR2, r15              ; Store CCR2 value for next pass
-        cmp     #DCO_FSET, r12          ; DCO_FSET= SMCLK/(32768/4)
-        jl      .LfllI                  ;
-        jeq     .LfllOK                 ;
-.LfllD: dec.b   &DCOCTL                 ; Decrement value
-        jmp     .Lwait0                 ;
-.LfllI: inc.b   &DCOCTL                 ; Increment value
-        jmp     .Lwait0                 ;
-
-.LfllER:                                ; error, currently ingnored
-.LfllOK:clr     &CCTL2                  ; stop CCR2
-        ret                             ;
index cb99613037ab0d9a84607955a4aee5915b01a707..9255487742347937028781b7d312328b1893da6f 100644 (file)
@@ -1,9 +1,6 @@
 #ifndef HARDWARE_H
 #define HARDWARE_H
 
-#define __msp430_have_port3
-#define __MSP430_HAS_PORT3__
-
 #include <io.h>
 #include <signal.h>
 #include <iomacros.h>
@@ -18,66 +15,20 @@ sfrw(QCNTH,QCNTH_);
 #define QCNT_VECTOR        14
 
 
-//PINS
-//PORT1
-#define TX              BIT1
-
-//PORT2
-#define RX              BIT2
-#define LED             BIT1
-
-//Port Output Register 'P1OUT, P2OUT':
-#define P1OUT_INIT      TX              //Init Output data of port1
-#define P2OUT_INIT      0               //Init Output data of port2
-#define P3OUT_INIT      0               //Init Output data of port3
-
-//Port Direction Register 'P1DIR, P2DIR':
-#define P1DIR_INIT      TX              //Init of Port1 Data-Direction Reg (Out=1 / Inp=0)
-#define P2DIR_INIT      ~RX             //Init of Port2 Data-Direction Reg (Out=1 / Inp=0)
-#define P3DIR_INIT      0xff            //Init of Port3 Data-Direction Reg (Out=1 / Inp=0)
-
-//Selection of Port or Module -Function on the Pins 'P1SEL, P2SEL'
-#define P1SEL_INIT      0               //P1-Modules:
-#define P2SEL_INIT      RX              //P2-Modules:
-#define P3SEL_INIT      0               //P3-Modules:
-
-//Interrupt capabilities of P1 and P2
-#define P1IE_INIT       0               //Interrupt Enable (0=dis 1=enabled)
-#define P2IE_INIT       0               //Interrupt Enable (0=dis 1=enabled)
-#define P1IES_INIT      0               //Interrupt Edge Select (0=pos 1=neg)
-#define P2IES_INIT      0               //Interrupt Edge Select (0=pos 1=neg)
-
-#define IE_INIT         0
-#define WDTCTL_INIT     WDTPW|WDTHOLD
-
-#define BCSCTL1_FLL     XT2OFF|DIVA1|RSEL2|RSEL0
-#define BCSCTL2_FLL     0
-#define TACTL_FLL       TASSEL_2|TACLR
-#define CCTL2_FLL       CM0|CCIS0|CAP
-
-#define TACTL_AFTER_FLL TASSEL_2|TACLR|ID_0
-
-//#define BAUD            40              //9600 @3MHz div 8
-//#define BAUD            20              //19200 @3MHz div 8
-//#define BAUD            20              //9600 @1.5MHz div 8
-//#define BAUD            140              //9600 @1.5MHz div 8
-
-//#define BAUD           2083              //9600 @20.0MHz div 1
-//#define BAUD           1042              //19200 @20.0MHz div 1
-//#define BAUD            521              //38400 @20.0MHz div 1
-//#define BAUD            347              //57600 @20.0MHz div 1
-//#define BAUD            174              //115200 @20.0MHz div 1
-//#define BAUD             87              //230400 @20.0MHz div 1
-
-#define BAUD            208              //115200 @24.0MHz div 1
+//HW UART registers
+#define UART_OFFSET        0x0100
 
-//Selection of 'Digitally Controlled Oszillator' (desired frquency in HZ, 1..3 MHz)
-#define DCO_FREQ        1536000         //3072000/2 makes 9600 a bit more precise
+#define UBAUD_             UART_OFFSET + 00
+#define UTX_               UART_OFFSET + 02
+#define URX_               UART_OFFSET + 04
+#define USTAT_             UART_OFFSET + 06
+#define UIE_               UART_OFFSET + 07
 
-//Automatic, do not edit
-#define DCO_FSET        (DCO_FREQ/8192) //DCO_FSET = DCO_FREQ / (32768/4)
-#define DCOCTL_MAX      0xff            // Used from FLL to check when Rsel must be changed
-#define DCOCTL_MIN      0               // Used from FLL to check when Rsel must be changed
+sfrw(UBAUD, UBAUD_);
+sfrb(UTX, UTX_);
+sfrb(URX, URX_);
+sfrb(USTAT, USTAT_);
+sfrb(UIE, UIE_);
 
 
-#endif //HARDWARE_H
+#endif
index bf98951974bc10d20af9a79ed132be1a8d24b067..1f2c2efef5cddbb93f570766afd8b1124f4b7954 100644 (file)
@@ -1,25 +1,29 @@
-/*
-see README.txt for details.
+/**
+This is a sample application for openMSP430 softcore MCU with external HW UART
+peripheral <git@rtime.felk.cvut.cz:fpga/uart> and quadcount peripheral.
 
-original by: chris <cliechti@gmx.net>
+First of all "Hello world" is printed and then application works like echo and
+also prints quadrature count whenever its value is changed (only whole turns
+are reported).
 
-modified by: Vladimir Burian <buriavl2@fel.cvut.cz>
+Baudrate is set to 115200.
 */
+
 #include "hardware.h"
 #include <stdlib.h>
 #include <stdio.h>
-#include "swuart.h"
-#include "fll.h"
+#include "uart.h"
+
 
 /**
 QuadCounter value
 */
 inline uint32_t qcount() {
   uint32_t result = 0;
-  
+
   result |= QCNTL;
   result |= ((uint32_t)QCNTH << 16);
-  
+
   return result;
 }
 
@@ -31,100 +35,62 @@ interrupt(QCNT_VECTOR) qcount_isr() {
 }
 
 
+/**
+Print bits of byte in format b'xxxxxxxx'
+*/
+void print_byte_flags(char flags) {
+  int i;
+
+  putchar('b');
+  putchar('\'');
+
+  for (i = 8;  i != 0;  i--) {
+    if ((flags & 0x80) != 0) {
+      putchar('1');
+    } else {
+      putchar('0');
+    }
+
+    flags = flags << 1;
+  }
+
+  putchar('\'');
+  putchar('\n');
+}
+
+
 /**
 Delay function.
 */
-void delay(unsigned int d) {
-   while(d--) {
+void delay(unsigned long int a, unsigned long int b) {
+  unsigned long int i;
+
+  while (a--) {
+    i = b;
+    while (i--) {
       nop();
       nop();
-   }
+    }
+  }
 }
 
+
 /**
-Main function with init an an endless loop that is synced with the
-interrupts trough the lowpower mode.
+Main function with init and an endless loop.
 */
 int main(void) {
-    int reading = 0;
-    int pos = 0;
-    char buf[40];
-    int led = 0;
-    
-    WDTCTL = WDTCTL_INIT;               //Init watchdog timer
-
-    P1OUT  = P1OUT_INIT;                //Init output data of port1
-    P1SEL  = P1SEL_INIT;                //Select port or module -function on port1
-    P1DIR  = P1DIR_INIT;                //Init port direction register of port1
-    P1IES  = P1IES_INIT;                //init port interrupts
-    P1IE   = P1IE_INIT;
-
-    P2OUT  = P2OUT_INIT;                //Init output data of port2
-    P2SEL  = P2SEL_INIT;                //Select port or module -function on port2
-    P2DIR  = P2DIR_INIT;                //Init port direction register of port2
-    P2IES  = P2IES_INIT;                //init port interrupts
-    P2IE   = P2IE_INIT;
-
-    P3DIR  = 0xff;
-    P3OUT  = 0xff;                      //light LED during init
-    delay(65535);                       //Wait for watch crystal startup
-    delay(65535);
-//  fllInit();                          //Init FLL to desired frequency using the 32k768 cystal as reference.
-    P3OUT  = 0x00;                      //switch off LED
-    
-    TACTL  = TACTL_AFTER_FLL;           //setup timer (still stopped)
-    CCTL0  = CCIE|CAP|CM_2|CCIS_1|SCS;  //select P2.2 with UART signal
-    CCTL1  = 0;                         //
-    CCTL2  = 0;                         //
-    TACTL |= MC1;                       //start timer
-    
+
+    //UBAUD = 0x04E1;                     //24.00MHz - 9600 baud
+    UBAUD = 0x0067;                     //24.00MHz - 115200 baud
+
     eint();                             //enable interrupts
-    
-    printf("\r\n====== openMSP430 in action ======\r\n");   //say hello
-    printf("\r\nSimple Line Editor Ready\r\n");   //say hello
-    
-    printf("\n[QCount = 0x%08lX]\n", qcount());
-    
-    while (1) {                         //main loop, never ends...
-        printf("> ");                   //show prompt
-        reading = 1;
-        while (reading) {               //loop and read characters
-            LPM0;                       //sync, wakeup by irq
-
-           led++;                      // Some lighting...
-           if (led==9) {
-             led = 0;
-           }
-           P3OUT = (0x01 << led);
-
-            switch (rxdata) {
-                //process RETURN key
-                case '\r':
-                //case '\n':
-                    printf("\r\n");     //finish line
-                    buf[pos++] = 0;     //to use printf...
-                    printf(":%s\r\n", buf);
-                    reading = 0;        //exit read loop
-                    pos = 0;            //reset buffer
-                    break;
-                //backspace
-                case '\b':
-                    if (pos > 0) {      //is there a char to delete?
-                        pos--;          //remove it in buffer
-                        putchar('\b');  //go back
-                        putchar(' ');   //erase on screen
-                        putchar('\b');  //go back
-                    }
-                    break;
-                //other characters
-                default:
-                    //only store characters if buffer has space
-                    if (pos < sizeof(buf)) {
-                        putchar(rxdata);     //echo
-                        buf[pos++] = rxdata; //store
-                    }
-            }
-        }
+
+
+    puts("Hello world\n");
+
+    for (;;) {  
+      putchar(getchar());
     }
+
 }
 
index ca0bdb856044bef82036793c9c836591a1eac97f..11b5623a9dbff7386a0fd7407c6b80461d17bec4 100644 (file)
@@ -1,6 +1,6 @@
 # makfile configuration
 NAME            = ta_uart
-OBJECTS         = main.o swuart.o fll.o
+OBJECTS         = main.o uart.o
 CPU             = msp430x1121
 
 ASFLAGS         = -mmcu=${CPU} -mforce-hwmul -x assembler-with-cpp -D_GNU_ASSEMBLER_ -c
@@ -50,6 +50,5 @@ dist:
 FORCE:
 
 #project dependencies
-main.o: main.c hardware.h
-fll.o: fll.s hardware.h
-swuart.o: swuart.s hardware.h
+main.o: main.c uart.h hardware.h
+uart.o: uart.h hardware.h
diff --git a/software/miniterm.py b/software/miniterm.py
deleted file mode 100644 (file)
index d0bd887..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-#!/usr/bin/env python
-#very simple serial terminal
-#http://pyserial.sf.net package required
-#input characters are sent directly, received characters are displays as is
-#baudrate and echo configuartion is done through globals:
-
-#<cliechti@gmx.net>
-
-import sys, os, serial, threading, getopt
-#EXITCHARCTER = '\x1b'   #ESC
-EXITCHARCTER = '\x04'   #ctrl+d
-
-#first choosea platform dependant way to read single characters from the console
-if os.name == 'nt': #sys.platform == 'win32':
-    import msvcrt
-    def getkey():
-        while 1:
-            if echo:
-                z = msvcrt.getche()
-            else:
-                z = msvcrt.getch()
-            if z == '\0' or z == '\xe0':    #functions keys
-                msvcrt.getch()
-            else:
-                return z
-
-elif os.name == 'posix':
-    #XXX: Untested code derrived from the Python FAQ....
-#    import termios, TERMIOS, sys, os
-    import termios, sys, os
-    fd = sys.stdin.fileno()
-    old = termios.tcgetattr(fd)
-    new = termios.tcgetattr(fd)
-    new[3] = new[3] & ~TERMIOS.ICANON & ~TERMIOS.ECHO
-    new[6][TERMIOS.VMIN] = 1
-    new[6][TERMIOS.VTIME] = 0
-    termios.tcsetattr(fd, TERMIOS.TCSANOW, new)
-    s = ''    # We'll save the characters typed and add them to the pool.
-    def getkey():
-        c = os.read(fd, 1)
-        if echo: sys.stdout.write(c)
-        return c
-    def clenaup_console():
-        termios.tcsetattr(fd, TERMIOS.TCSAFLUSH, old)
-    sys.exitfunc = clenaup_console  #terminal modes have to be restored on exit...
-
-else:
-    raise "Sorry no implementation for your platform (%s) available." % sys.platform
-
-
-def reader():
-    """loop forever and copy serial->console"""
-    while 1:
-        sys.stdout.write(s.read())
-
-def writer():
-    """loop forever and copy console->serial"""
-    while 1:
-        c = getkey()
-        if c == EXITCHARCTER: break   #exit on esc
-        s.write(c)              #send character
-        if convert_outgoing_cr and c == '\r':
-            s.write('\n')
-            if echo: sys.stdout.write('\n')
-
-
-#print a short help message
-def usage():
-    print >>sys.stderr, """USAGE: %s [options]
-    Simple Terminal Programm for the serial port.
-
-    options:
-    -p, --port=PORT: port, a number, defualt = 0 or a device name
-    -b, --baud=BAUD: baudrate, default 9600
-    -r, --rtscts:    enable RTS/CTS flow control (default off)
-    -x, --xonxoff:   enable software flow control (default off)
-    -e, --echo:      enable local echo (default off)
-    -c, --cr:        disable CR -> CR+LF translation
-
-    """ % sys.argv[0]
-
-if __name__ == '__main__':
-    #parse command line options
-    try:
-        opts, args = getopt.getopt(sys.argv[1:],
-                "hp:b:rxec",
-                ["help", "port=", "baud=", "rtscts", "xonxoff", "echo", "cr"])
-    except getopt.GetoptError:
-        # print help information and exit:
-        usage()
-        sys.exit(2)
-    
-    port  = 0
-    baudrate = 9600
-    echo = 0
-    convert_outgoing_cr = 1
-    rtscts = 0
-    xonxoff = 0
-    for o, a in opts:
-        if o in ("-h", "--help"):   #help text
-            usage()
-            sys.exit()
-        elif o in ("-p", "--port"):   #specified port
-            try:
-                port = int(a)
-            except ValueError:
-                port = a
-        elif o in ("-b", "--baud"):   #specified baudrate
-            try:
-                baudrate = int(a)
-            except ValueError:
-                raise ValueError, "Baudrate must be a integer number"
-        elif o in ("-r", "--rtscts"):
-            rtscts = 1
-        elif o in ("-x", "--xonxoff"):
-            xonxoff = 1
-        elif o in ("-e", "--echo"):
-            echo = 1
-        elif o in ("-c", "--cr"):
-            convert_outgoing_cr = 0
-
-    try:
-        s = serial.Serial(port, baudrate, rtscts=rtscts, xonxoff=xonxoff)
-    except:
-        print "could not open port"
-        sys.exit(1)
-    print "--- Miniterm --- type Ctrl-D to quit"
-    #start serial->console thread
-    r = threading.Thread(target=reader)
-    r.setDaemon(1)
-    r.start()
-    #enter console->serial loop
-    writer()
-
-    print "\n--- exit ---"
diff --git a/software/swuart.h b/software/swuart.h
deleted file mode 100644 (file)
index 140712f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef SWUART_H
-#define SWUART_H
-
-void serPutc(char);             //send one character over timer_a uart
-extern char rxdata;
-#endif //SWUART_H
diff --git a/software/swuart.s b/software/swuart.s
deleted file mode 100644 (file)
index dc17823..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-#include "hardware.h"
-
-;variables
-.data
-        .comm   rxdata,1,1              ;char var
-        .comm   rxshift,1,1             ;char var
-        .comm   rxbit,2,2               ;short var, aligned
-
-.text
-
-interrupt(TIMERA0_VECTOR)               ;register interrupt vector
-;interrupt handler to receive as Timer_A UART
-.global ccr0                            ;place a label afterwards so
-ccr0:                                   ;that it is used in the listing
-        add     rxbit, r0
-        jmp     .Lrxstart               ;start bit
-        jmp     .Lrxdatabit             ;D0
-        jmp     .Lrxdatabit             ;D1
-        jmp     .Lrxdatabit             ;D2
-        jmp     .Lrxdatabit             ;D3
-        jmp     .Lrxdatabit             ;D4
-        jmp     .Lrxdatabit             ;D5
-        jmp     .Lrxdatabit             ;D6
-;        jmp     .Lrxlastbit             ;D7 that one is following anyway
-        
-.Lrxlastbit:                            ;last bit, handle byte
-        bit     #SCCI, &CCTL0           ;read last bit
-        rrc.b   rxshift                 ;and save it
-        clr     rxbit                   ;reset state
-        mov     #CCIE|CAP|CM_2|CCIS_1|SCS, &CCTL0   ;restore capture mode
-        mov.b   rxshift, rxdata         ;copy received data
-        bic     #CPUOFF|OSCOFF|SCG0|SCG1, 0(r1) ;exit all lowpower modes
-        ;here you might do other things too, like setting a flag
-        ;that the wakeup comes from the Timer_A UART. however
-        ;it should not take longer than one bit time, otherwise
-        ;charcetrs will be lost.
-        reti
-
-.Lrxstart:                              ;startbit, init
-        clr     rxshift                 ;clear input buffer
-        add     #(BAUD/2), &CCR0        ;startbit + 1.5 bits -> first bit
-        mov     #CCIE|CCIS_1|SCS, &CCTL0;set compare mode, sample bits
-        jmp     .Lrxex                  ;set state,...
-
-.Lrxdatabit:                            ;save databit
-        bit     #SCCI, &CCTL0           ;measure databit
-        rrc.b   rxshift                 ;rotate in databit
-
-.Lrxex: add     #BAUD, &CCR0            ;one bit delay
-        incd    rxbit                   ;setup next state
-        reti
-
-; void serPutc(char)
-;use an other Capture/Compare than for receiving (full duplex).
-;this one is without interrupts and OUTMOD, because only
-;this way P1.1 can be used. P1.1 is prefered because the
-;BSL is on that pin too.
-.global putchar
-        .type putchar, @function
-putchar:                                ;send a byte
-        mov     #0, &CCTL1              ;select compare mode
-        mov     #10, r13                ;ten bits: Start, 8 Data, Stop
-        rla     r15                     ;shift in start bit (0)
-        bis     #0x0200, r15            ;set tenth bit (1), thats the stop bit
-        mov     &TAR, &CCR1             ;set up start time
-.Lt1lp: add     #BAUD, &CCR1            ;set up for one bit
-        rrc     r15                     ;shift data trough carry
-        jc      .Lt1                    ;test carry bit
-.Lt0:   bic.b   #TX, &P1OUT             ;generate pulse
-        jmp     .Ltc                    ;
-.Lt1:   bis.b   #TX, &P1OUT             ;just use the same amount of time as for a zero
-        jmp     .Ltc                    ;
-.Ltc:   bit     #CCIFG, &CCTL1          ;wait for compare
-        jz      .Ltc                    ;loop until the bit is set
-        bic     #CCIFG, &CCTL1          ;clear for next loop
-        dec     r13                     ;decrement bit counter
-        jnz     .Lt1lp                  ;loop until all bits are transmitted
-        ret
diff --git a/software/uart.c b/software/uart.c
new file mode 100644 (file)
index 0000000..1c57831
--- /dev/null
@@ -0,0 +1,14 @@
+#include "hardware.h"
+#include "uart.h"
+
+int putchar(int c) {
+  while (USTAT & 0x20) {}
+  UTX = c;
+  return 0;
+}
+
+int getchar() {
+  while (!(USTAT & 0x10)) {}
+  return URX;
+}
+
diff --git a/software/uart.h b/software/uart.h
new file mode 100644 (file)
index 0000000..c3290b4
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef UART_H
+#define UART_H
+
+int putchar(int c);
+
+int getchar();
+
+#endif
+