diff --git a/pycardium/mphalport.c b/pycardium/mphalport.c
index ee9e2f44fb7321c7dd5c3c5e1a5b9522575844e6..bc029664b632068be810862e96d61a9e201bff32 100644
--- a/pycardium/mphalport.c
+++ b/pycardium/mphalport.c
@@ -1,6 +1,7 @@
 #include <stdint.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "py/lexer.h"
 #include "py/mpconfig.h"
@@ -27,12 +28,36 @@ int mp_hal_stdin_rx_chr(void)
 	return (int)epic_uart_read_chr();
 }
 
-/* Send string of given length */
+/* Send a string */
 void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len)
 {
 	epic_uart_write_str(str, len);
 }
 
+/* Send a string, but replace \n with \n\r */
+void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len)
+{
+	/*
+	 * Only print one line at a time.  Insert `\r` between lines so
+	 * they are properly displayed on the serial console.
+	 */
+	size_t i, last = 0;
+	for (i = 0; i < len; i++) {
+		if (str[i] == '\n') {
+			epic_uart_write_str(&str[last], i - last);
+			epic_uart_write_str("\r", 1);
+			last = i;
+		}
+	}
+	epic_uart_write_str(&str[last], len - last);
+}
+
+/* Send a zero-terminated string */
+void mp_hal_stdout_tx_str(const char *str)
+{
+	mp_hal_stdout_tx_strn(str, strlen(str));
+}
+
 /* Used by MicroPython for debug output */
 int DEBUG_printf(const char *fmt, ...)
 {
@@ -90,6 +115,11 @@ void mp_hal_delay_us(mp_uint_t us)
 	mxc_delay(us);
 }
 
+mp_uint_t mp_hal_ticks_ms(void)
+{
+	return 0;
+}
+
 /******************************************************************************
  * Fatal Errors
  */
diff --git a/pycardium/mphalport.h b/pycardium/mphalport.h
index 79e25cde78d3836281bc2d03c1dec87fc1c19be6..ad34087f9e76adf004f2a7d765e736534bfbcab1 100644
--- a/pycardium/mphalport.h
+++ b/pycardium/mphalport.h
@@ -1,9 +1,3 @@
 #include "py/mpconfig.h"
 
-/* TODO: Replace this with a proper implementation */
-static inline mp_uint_t mp_hal_ticks_ms(void)
-{
-	return 0;
-}
-
 void mp_hal_set_interrupt_char(char c);