X-Git-Url: http://git.subgeniuskitty.com/pdp11-modern-c/.git/blobdiff_plain/846f4d60e4994a39decd6c27463411f53965fc60..202004d54803c861f7fbaa9169eaad750c63f7cf:/pdp11/pdp11_slu.c diff --git a/pdp11/pdp11_slu.c b/pdp11/pdp11_slu.c new file mode 100644 index 0000000..1d4667c --- /dev/null +++ b/pdp11/pdp11_slu.c @@ -0,0 +1,132 @@ +// (c) 2020 Aaron Taylor +// See License.txt file for copyright and license details. + +#include +#include +#include "pdp11.h" + +/* + * Polled console I/O + */ + +void +putch(uint16_t c) +{ + while(!(GET(CONSXCSR,SLUXCSR_XMTRDY))) continue; + CONSXBUF = c; +} + +uint16_t +getch(void) +{ + while(!(GET(CONSRCSR,SLURCSR_RCVRDY))) continue; + return CONSRBUF; +} + + +/* + * Helper functions for use with console IO + */ + +void +print_string(const char * string) +{ + while (*string != '\0') { + putch(*string); + string++; + } +} + +char +digit_to_ascii(uint16_t digit) +{ + if (digit > 15) { + print_string("ERROR: Out of range in digit_to_ascii()\r\n"); + // TODO: How do I want to handle runtime errors? + return 0; + } else if (digit > 9) { + digit -= 10; + digit += 'a'; + return digit; + } else { + digit += '0'; + return digit; + } +} + +void +print_uint16_in_octal(uint16_t number) +{ + char output[7]; // +6 for digits; +1 for null-term + for (int i = 5; i >= 0; i--) { + output[i] = digit_to_ascii(number % 8); + number = number / 8; + } + output[6] = '\0'; + putch('0'); + print_string(output); +} + +void +printf(const char * format, ...) +{ + va_list ap; + va_start(ap, format); + while (*format) { + switch (*format) { + case '%': + format++; + switch (*format) { + case 's': + { + char * s = va_arg(ap, char *); + print_string(s); + break; + } + case 'o': + { + uint16_t u = va_arg(ap, unsigned int); + print_uint16_in_octal(u); + break; + } + default: + /* Put it back and look innocent. */ + putch('%'); + putch(*format); + break; + } + break; + case '\\': + format++; + switch (*format) { + case 'n': + print_string("\r\n"); + break; + case 't': + putch('\t'); + break; + case '%': + putch('%'); + break; + case '\\': + putch('\\'); + break; + default: + /* Maybe this escape wasn't meant for us. */ + putch('\\'); + putch(*format); + break; + } + break; + case '\n': + print_string("\r\n"); + break; + default: + putch(*format); + break; + } + format++; + } + va_end(ap); +} +