2019-07-17 01:04:04 +00:00
|
|
|
/************************
|
|
|
|
*** Team Kitty, 2019 ***
|
|
|
|
*** Sync ***
|
|
|
|
***********************/
|
|
|
|
|
|
|
|
/* This file provides an interface to the serial port.
|
|
|
|
* Most emulators allow the serial port to be saved into
|
|
|
|
* a text buffer, or a file, but this code should work on
|
|
|
|
* hardware with an actual serial port and monitor. */
|
|
|
|
|
2019-07-22 21:32:35 +00:00
|
|
|
/* After the development of Syncboot, this becomes a little bit harder.
|
|
|
|
* Some testing will be needed to know for certain whether this will work.
|
|
|
|
* Until then, this is to be put on hold. 21/07/19 - Curle */
|
|
|
|
|
2019-07-24 20:49:35 +00:00
|
|
|
#include <kernel.h>
|
2019-04-07 14:34:15 +00:00
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
#define SERIAL_DATA(base) (base)
|
|
|
|
#define SERIAL_DLAB(base) (base + 1)
|
|
|
|
#define SERIAL_FIFO(base) (base + 2)
|
|
|
|
#define SERIAL_LINE(base) (base + 3)
|
|
|
|
#define SERIAL_MODEM(base) (base + 4)
|
|
|
|
#define SERIAL_LINE_STATUS(base) (base + 5)
|
|
|
|
#define COM1 0x3F8
|
2019-04-07 14:34:15 +00:00
|
|
|
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
/** serialSetBaudrate:
|
2019-04-07 14:34:15 +00:00
|
|
|
* Sets the speed that data is sent via the serial port.
|
|
|
|
* The default speed is 115200 bits/s.
|
|
|
|
* The argument given is the divisor of the number.
|
|
|
|
* Hence, the new speed becomes (115200/divisor) bits/s.
|
|
|
|
*
|
|
|
|
* @param divisor The new divisor for the baud rate.
|
|
|
|
*/
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
void serialSetBaudrate() {
|
|
|
|
WritePort(SERIAL_LINE(COM1), 0x80, 1);
|
2019-04-07 14:34:15 +00:00
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
WritePort(SERIAL_DATA(COM1), 0x03, 1);
|
2019-04-07 14:34:15 +00:00
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
WritePort(SERIAL_DLAB(COM1), 0x00, 1);
|
2019-04-07 14:34:15 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
/** serialConfigure:
|
2019-04-07 14:34:15 +00:00
|
|
|
* Sets a specific data byteset in the Serial hardware.
|
|
|
|
* Required for expected operation.
|
|
|
|
*/
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
void serialConfigure() {
|
2019-08-20 15:39:20 +00:00
|
|
|
/* Bit: | 7 | 6 | 5 4 3 | 2 | 1 0 |
|
|
|
|
* Content: | d | b | parity | s | dl |
|
|
|
|
* Value: | 0 | 0 | 0 0 0 | 0 | 1 1 | = 0x03
|
2019-04-07 14:34:15 +00:00
|
|
|
*/
|
2019-09-11 02:58:20 +00:00
|
|
|
WritePort(SERIAL_LINE(COM1), 0x03, 1);
|
2019-04-07 14:34:15 +00:00
|
|
|
}
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
/** serialConfigureBuffers:
|
2019-04-07 14:34:15 +00:00
|
|
|
* Enables FIFO (First In First Out) on the Serial line.
|
|
|
|
* It clears both the receive and transmit queues.
|
|
|
|
* It uses a 14 byte wide queue.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
void serialConfigureBuffers() {
|
2019-04-07 14:34:15 +00:00
|
|
|
/* Bit: | 7 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
|
|
|
* Content: | 1v1 | bs | r | dma | clt | clr | e |
|
|
|
|
* Value: | 1 1 | 0 | 0 | 0 | 1 | 1 | 1 | = 0xC7
|
|
|
|
*/
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
WritePort(SERIAL_FIFO(COM1), 0xC7, 1);
|
2019-04-07 14:34:15 +00:00
|
|
|
}
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
/** serialConfigureModem:
|
2019-04-07 14:34:15 +00:00
|
|
|
*/
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
void serialConfigureModem() {
|
2019-04-07 14:34:15 +00:00
|
|
|
/* Bit: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
|
|
|
* Content: | r | r | af | lb | ao2 | ao1 | rts | dtr |
|
|
|
|
* Value: | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | = 0x03
|
|
|
|
*/
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
WritePort(SERIAL_MODEM(COM1), 0x03, 1);
|
2019-04-07 14:34:15 +00:00
|
|
|
}
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
/** serialCheck:
|
2019-04-07 14:34:15 +00:00
|
|
|
* Checks whether the Transmit FIFO Queue is empty on the given port.
|
|
|
|
*
|
|
|
|
* @return 0 If the queue is not empty.
|
|
|
|
* 1 If the queue is empty.
|
|
|
|
*/
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
int serialCheck() {
|
|
|
|
return ReadPort(SERIAL_LINE_STATUS(COM1), 1) & 0x20;
|
2019-04-07 14:34:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/** serial_write:
|
|
|
|
* Prints a single character to the serial port.
|
|
|
|
* Does nothing fancy.
|
|
|
|
* @param data The character to write.
|
|
|
|
*/
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
void serialWrite(const char chr) {
|
2019-04-07 14:34:15 +00:00
|
|
|
//Hang until we have access to the COM port.
|
2019-09-11 02:58:20 +00:00
|
|
|
while(!serialCheck());
|
|
|
|
WritePort(COM1, chr, 1);
|
2019-04-07 14:34:15 +00:00
|
|
|
}
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
/** serialPrint:
|
2019-04-07 14:34:15 +00:00
|
|
|
* Prints a string to the serial port.
|
|
|
|
* Does not support ANSI codes, or color.
|
|
|
|
*
|
|
|
|
* @param data The string to write.
|
|
|
|
*/
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
void serialPrint(const char* data) {
|
2019-04-07 14:34:15 +00:00
|
|
|
for(size_t i = 0; i < strlen(data); i++) {
|
2019-09-11 02:58:20 +00:00
|
|
|
serialWrite(data[i]);
|
2019-04-07 14:34:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
/** serialPrintf:
|
2019-04-07 14:34:15 +00:00
|
|
|
* A printf-style function for the serial port.
|
|
|
|
*
|
|
|
|
* @param format The base string - used to substitute the succeding values.
|
|
|
|
* @param ... The substitutions.
|
|
|
|
*/
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
void serialPrintf(const char* format, ...) {
|
2019-04-07 14:34:15 +00:00
|
|
|
uint32_t storage; //To hold temporary variables
|
|
|
|
char stringstore[10] = {0}; //To convert ints to strings.
|
|
|
|
va_list list;
|
|
|
|
va_start(list, format);
|
|
|
|
|
|
|
|
for(size_t i = 0; i < strlen(format); i++) {
|
|
|
|
//Check for the format specifier
|
|
|
|
if(format[i] == '%') {
|
|
|
|
//Check for the other specs
|
|
|
|
if(format[i+1] == 'd') {
|
|
|
|
|
|
|
|
storage = va_arg(list, int);
|
2019-09-11 02:58:20 +00:00
|
|
|
inttoa(storage, stringstore);
|
|
|
|
serialPrint(stringstore);
|
|
|
|
zeroString(stringstore);
|
2019-04-07 14:34:15 +00:00
|
|
|
i += 2;
|
|
|
|
|
|
|
|
} else if(format[i+1] == 'x') {
|
|
|
|
|
|
|
|
storage = va_arg(list, int);
|
2019-09-11 02:58:20 +00:00
|
|
|
itoh(storage, stringstore);
|
|
|
|
serialPrint(stringstore);
|
|
|
|
zeroString(stringstore);
|
2019-04-07 14:34:15 +00:00
|
|
|
i += 2;
|
|
|
|
|
|
|
|
} else if(format[i+1] == 's') {
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
serialPrint(va_arg(list, char*));
|
2019-04-07 14:34:15 +00:00
|
|
|
i += 2;
|
|
|
|
|
|
|
|
} else {
|
2019-09-11 02:58:20 +00:00
|
|
|
serialPrint("ERROR: Attempting to parse unknown format string.");
|
2019-04-07 14:34:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
2019-09-11 02:58:20 +00:00
|
|
|
serialWrite(format[i]);
|
2019-04-07 14:34:15 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
va_end(list); //Free the list
|
|
|
|
}
|
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
void serialInit() {
|
2019-04-07 14:34:15 +00:00
|
|
|
// Disable interrupts
|
2019-09-11 02:58:20 +00:00
|
|
|
WritePort(SERIAL_DLAB(COM1), 0x00, 1);
|
2019-04-07 14:34:15 +00:00
|
|
|
|
2019-09-11 02:58:20 +00:00
|
|
|
// Set baud rate divisor to 3
|
|
|
|
serialSetBaudrate();
|
2019-04-07 14:34:15 +00:00
|
|
|
// 8 bits, no parity, one stop bit.
|
2019-09-11 02:58:20 +00:00
|
|
|
serialConfigure();
|
2019-04-07 14:34:15 +00:00
|
|
|
// Enable FIFO and clear buffers.
|
2019-09-11 02:58:20 +00:00
|
|
|
serialConfigureBuffers();
|
2019-04-07 14:34:15 +00:00
|
|
|
// Enable IRQs, RTS/DSR set.
|
2019-09-11 02:58:20 +00:00
|
|
|
serialConfigureModem();
|
2019-04-07 14:34:15 +00:00
|
|
|
}
|