Skip to content

Instantly share code, notes, and snippets.

@kikairoya
Created July 21, 2010 15:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kikairoya/484637 to your computer and use it in GitHub Desktop.
Save kikairoya/484637 to your computer and use it in GitHub Desktop.
#include "sci.hpp"
#include <stddef.h>
#define set_imask_ccr(b) (b ? ({asm volatile ("orc #0x80, ccr");}) : ({asm volatile ("andc #0x7F, ccr");}))
#define get_imask_ccr() ({ unsigned char __r; asm volatile ("stc.b ccr, %s0": "=r"(__r)); !!(__r&0x80); })
struct lock_interrupt {
__attribute__((always_inline)) lock_interrupt() : masked(get_imask_ccr()) {
set_imask_ccr(1);
}
__attribute__((always_inline)) ~lock_interrupt() {
set_imask_ccr(masked);
}
bool masked;
};
struct fifo_t {
static const size_t bufsize = sci::bufsize;
unsigned char buf[bufsize];
unsigned wp;
unsigned rp;
void push(unsigned char c) { return static_cast<volatile fifo_t *>(this)->push(c); }
void push(unsigned char c) volatile {
unsigned p = wp;
buf[p++] = c;
p %= bufsize;
if (p!=rp) wp = p;
}
void pop() { return static_cast<volatile fifo_t *>(this)->pop(); }
void pop() volatile {
unsigned p = rp;
if (wp!=p) rp = (p+1) % bufsize;
}
unsigned char top() const volatile { return buf[rp]; }
bool empty() const volatile { return wp==rp; }
bool full() const volatile { return (wp+1)%bufsize==rp; }
};
struct fifo_pair_t{
fifo_t tx, rx;
};
static volatile fifo_pair_t g_fifo;
void sci::init() {
IO.PMR1.BIT.TXD = 1;
//SCI3.BRR = 10; // 20MHz, 57600bps
SCI3.BRR = 4; // 20MHz, 128000bps
for (volatile unsigned n=0; n<75; ++n) nop();
SCI3.SSR.BYTE = 0x80;
SCI3.SCR3.BYTE = 0xF0;
}
void sci::flush() {
lock_interrupt lk();
while (!g_fifo.tx.empty()) ;
g_fifo.rx.wp = g_fifo.rx.rp;
}
int sci::putc(int c) {
if (c=='\n' && EOF!='\r') putc('\r');
while (g_fifo.tx.full()) ;
lock_interrupt lk;
g_fifo.tx.push(static_cast<unsigned char>(c));
SCI3.SCR3.BIT.TIE = 1;
return c;
}
int sci::puts(const char *s) {
while (*s) putc(*s++);
return 0;
}
int sci::getc() {
SCI3.SCR3.BIT.RE = 1;
while (g_fifo.rx.empty()) ;
int c = g_fifo.rx.top();
lock_interrupt lk;
g_fifo.rx.pop();
if (c=='\r') {
if (g_fifo.rx.top()=='\n') g_fifo.rx.pop();
return '\n';
}
return c;
}
char *sci::gets(char *buf, int size) {
char *p = buf;
if (!buf || !size) return buf;
while (--size) {
switch (int c = getc()) {
case EOF:
case '\r':
case '\n':
goto done;
default:
*p++ = c;
}
}
done:
*p = 0;
return buf;
}
bool sci::readable() { return !g_fifo.rx.empty(); }
void int_sci3() {
if (SCI3.SSR.BYTE&0x38) SCI3.SSR.BYTE &= ~0x38;
if (SCI3.SSR.BIT.RDRF) {
unsigned char c = SCI3.RDR;
SCI3.SSR.BIT.RDRF = 0;
g_fifo.rx.push(c);
}
if (SCI3.SSR.BIT.TDRE) {
if (!g_fifo.tx.empty()) {
SCI3.TDR = g_fifo.tx.top();
g_fifo.tx.pop();
} else {
SCI3.SCR3.BIT.TIE = 0;
}
}
}
#ifndef SCI_HPP_
#define SCI_HPP_
struct sci {
static void init() __attribute__((constructor));
static void flush();
static int putc(int c);
static int puts(const char *s);
static int getc();
static char *gets(char *buf, int size);
static bool readable();
static const size_t bufsize = 12;
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment