diff --git a/src/energenie/drv/gpio_sim.c b/src/energenie/drv/gpio_sim.c index c8ce63e..f7a2871 100644 --- a/src/energenie/drv/gpio_sim.c +++ b/src/energenie/drv/gpio_sim.c @@ -5,8 +5,9 @@ /***** INCLUDES *****/ -#include // OPTIONAL +#include "system.h" #include "gpio.h" +#include "trace.h" /***** CONFIGURATION *****/ @@ -16,14 +17,6 @@ //#define GPIO_LOOPBACK -/* Printf is not available on some platforms, or not very efficient. - * These macros make it possible to re-map I/O to more efficient functions. - */ - -#define OUTS(s) printf("%s", s) -#define OUTN(n) printf("%d", (unsigned int)n) -#define OUTC(c) putc(c, stdout) -#define NL() OUTC('\n') /***** VARIABLES *****/ @@ -42,9 +35,9 @@ { #if defined(GPIO_DEBUG) //printf("gpio:in:%d\n", g); - OUTS("gpio:in:"); - OUTN(g); - NL(); + TRACE_OUTS("gpio:in:"); + TRACE_OUTN(g); + TRACE_NL(); #endif } @@ -53,9 +46,9 @@ { #if defined(GPIO_DEBUG) //printf("gpio:out:%d\n", g); - OUTS("gpio:out:"); - OUTN(g); - NL(); + TRACE_OUTS("gpio:out:"); + TRACE_OUTN(g); + TRACE_NL(); #endif } @@ -64,9 +57,9 @@ { #if defined(GPIO_DEBUG) //printf("gpio:high:%d\n", g); - OUTS("gpio:high:"); - OUTN(g); - NL(); + TRACE_OUTS("gpio:high:"); + TRACE_OUTN(g); + TRACE_NL(); #endif gpio_out[g] = 1; @@ -81,9 +74,9 @@ { #if defined(GPIO_DEBUG) //printf("gpio:low:%d\n", g); - OUTS("gpio:low:"); - OUTN(g); - NL(); + TRACE_OUTS("gpio:low:"); + TRACE_OUTN(g); + TRACE_NL(); #endif gpio_out[g] = 0; @@ -98,11 +91,11 @@ { #if defined(GPIO_DEBUG) //printf("gpio:write:%d=%d\n", g, v); - OUTS("gpio:write:"); - OUTN(g); - OUTC('='); - OUTN(v); - NL(); + TRACE_OUTS("gpio:write:"); + TRACE_OUTN(g); + TRACE_OUTC('='); + TRACE_OUTN(v); + TRACE_NL(); #endif gpio_out[g] = v; @@ -117,11 +110,11 @@ { #if defined(GPIO_DEBUG) //printf("gpio:read:%d=%d\n") - OUTS("gpio:read:"); - OUTN(g); - OUTC('='); - OUTN(gpio_in[g]); - NL(); + TRACE_OUTS("gpio:read:"); + TRACE_OUTN(g); + TRACE_OUTC('='); + TRACE_OUTN(gpio_in[g]); + TRACE_NL(); #endif return gpio_in[g]; } diff --git a/src/energenie/drv/hrf69_test.c b/src/energenie/drv/hrf69_test.c index b571360..f88a350 100644 --- a/src/energenie/drv/hrf69_test.c +++ b/src/energenie/drv/hrf69_test.c @@ -13,6 +13,7 @@ #include "gpio.h" #include "spi.h" #include "hrf69.h" +#include "trace.h" /***** CONFIGURATION *****/ @@ -74,6 +75,9 @@ // write a register and read it back +#define TX 0x04 +#define RX 0x0C + void hrf_test_connect(void) { uint8_t result; @@ -81,15 +85,31 @@ reset(); gpio_mock_set_in(MISO, 1); // force return bus high to test - printf("** write:%02X\n", (unsigned int) HRF_MODE_TRANSMITER); - HRF_writereg(HRF_ADDR_OPMODE, HRF_MODE_TRANSMITER); - result = HRF_readreg(0x00); - printf("** read:%02X\n", (unsigned int) result); + //printf("** write:%02X\n", (unsigned int) HRF_MODE_TRANSMITER); + TRACE_OUTS("** write:"); + TRACE_OUTN(TX); + TRACE_NL(); - printf("** write:%02X\n", (unsigned int) HRF_MODE_RECEIVER); - HRF_writereg(HRF_ADDR_OPMODE, HRF_MODE_RECEIVER); + HRF_writereg(HRF_ADDR_OPMODE, TX); result = HRF_readreg(0x00); - printf("** read:%02X\n", (unsigned int) result); + + //printf("** read:%02X\n", (unsigned int) result); + TRACE_OUTS("** read:"); + TRACE_OUTN(result); + TRACE_NL(); + + //printf("** write:%02X\n", (unsigned int) HRF_MODE_RECEIVER); + TRACE_OUTS("** write:"); + TRACE_OUTN(RX); + TRACE_NL(); + + HRF_writereg(HRF_ADDR_OPMODE, RX); + result = HRF_readreg(0x00); + + //printf("** read:%02X\n", (unsigned int) result); + TRACE_OUTS("** read:"); + TRACE_OUTN(result); + TRACE_NL(); spi_finished(); } diff --git a/src/energenie/drv/radio.c b/src/energenie/drv/radio.c index 93310fe..a41c0bb 100644 --- a/src/energenie/drv/radio.c +++ b/src/energenie/drv/radio.c @@ -1,451 +1,451 @@ -//TODO +/* radio.c D.J.Whale */ -# test1.py 26/09/2015 D.J.Whale -# -# Simple low level test of the HopeRF interface -# Uses direct SPI commands to exercise the interface. -# -# Receives and dumps payload buffers. -# -# Eventually a lot of this will be pushed into a separate module, -# and then pushed back into C once it is proved working. - -import spi - -def warning(msg): - print("warning:" + str(msg)) - -def trace(msg): - print(str(msg)) - - -def ashex(p): - line = "" - for b in p: - line += str(hex(b)) + " " - return line - - -#----- HOPERF REGISTER INTERFACE ---------------------------------------------- -# Precise register descriptions can be found in: -# www.hoperf.com/upload/rf/RFM69W-V1.3.pdf -# on page 63 - 74 - -ADDR_FIFO = 0x00 -ADDR_OPMODE = 0x01 -ADDR_REGDATAMODUL = 0x02 -ADDR_BITRATEMSB = 0x03 -ADDR_BITRATELSB = 0x04 -ADDR_FDEVMSB = 0x05 -ADDR_FDEVLSB = 0x06 -ADDR_FRMSB = 0x07 -ADDR_FRMID = 0x08 -ADDR_FRLSB = 0x09 -ADDR_AFCCTRL = 0x0B -ADDR_LNA = 0x18 -ADDR_RXBW = 0x19 -ADDR_AFCFEI = 0x1E -ADDR_IRQFLAGS1 = 0x27 -ADDR_IRQFLAGS2 = 0x28 -ADDR_RSSITHRESH = 0x29 -ADDR_PREAMBLELSB = 0x2D -ADDR_SYNCCONFIG = 0x2E -ADDR_SYNCVALUE1 = 0x2F -ADDR_SYNCVALUE2 = 0x30 -ADDR_SYNCVALUE3 = 0x31 -ADDR_SYNCVALUE4 = 0x32 -ADDR_PACKETCONFIG1 = 0x37 -ADDR_PAYLOADLEN = 0x38 -ADDR_NODEADDRESS = 0x39 -ADDR_FIFOTHRESH = 0x3C - -# HopeRF masks to set and clear bits -MASK_REGDATAMODUL_OOK = 0x08 -MASK_REGDATAMODUL_FSK = 0x00 -MASK_WRITE_DATA = 0x80 -MASK_MODEREADY = 0x80 -MASK_FIFONOTEMPTY = 0x40 -MASK_FIFOLEVEL = 0x20 -MASK_FIFOOVERRUN = 0x10 -MASK_PACKETSENT = 0x08 -MASK_TXREADY = 0x20 -MASK_PACKETMODE = 0x60 -MASK_MODULATION = 0x18 -MASK_PAYLOADRDY = 0x04 - -MODE_STANDBY = 0x04 # Standby -MODE_TRANSMITER = 0x0C # Transmiter -MODE_RECEIVER = 0x10 # Receiver -VAL_REGDATAMODUL_FSK = 0x00 # Modulation scheme FSK -VAL_REGDATAMODUL_OOK = 0x08 # Modulation scheme OOK -VAL_FDEVMSB30 = 0x01 # frequency deviation 5kHz 0x0052 -> 30kHz 0x01EC -VAL_FDEVLSB30 = 0xEC # frequency deviation 5kHz 0x0052 -> 30kHz 0x01EC -VAL_FRMSB434 = 0x6C # carrier freq -> 434.3MHz 0x6C9333 -VAL_FRMID434 = 0x93 # carrier freq -> 434.3MHz 0x6C9333 -VAL_FRLSB434 = 0x33 # carrier freq -> 434.3MHz 0x6C9333 -VAL_FRMSB433 = 0x6C # carrier freq -> 433.92MHz 0x6C7AE1 -VAL_FRMID433 = 0x7A # carrier freq -> 433.92MHz 0x6C7AE1 -VAL_FRLSB433 = 0xE1 # carrier freq -> 433.92MHz 0x6C7AE1 -VAL_AFCCTRLS = 0x00 # standard AFC routine -VAL_AFCCTRLI = 0x20 # improved AFC routine -VAL_LNA50 = 0x08 # LNA input impedance 50 ohms -VAL_LNA50G = 0x0E # LNA input impedance 50 ohms, LNA gain -> 48db -VAL_LNA200 = 0x88 # LNA input impedance 200 ohms -VAL_RXBW60 = 0x43 # channel filter bandwidth 10kHz -> 60kHz page:26 -VAL_RXBW120 = 0x41 # channel filter bandwidth 120kHz -VAL_AFCFEIRX = 0x04 # AFC is performed each time RX mode is entered -VAL_RSSITHRESH220 = 0xDC # RSSI threshold 0xE4 -> 0xDC (220) -VAL_PREAMBLELSB3 = 0x03 # preamble size LSB 3 -VAL_PREAMBLELSB5 = 0x05 # preamble size LSB 5 -VAL_SYNCCONFIG2 = 0x88 # Size of the Synch word = 2 (SyncSize + 1) -VAL_SYNCCONFIG4 = 0x98 # Size of the Synch word = 4 (SyncSize + 1) -VAL_SYNCVALUE1FSK = 0x2D # 1st byte of Sync word -VAL_SYNCVALUE2FSK = 0xD4 # 2nd byte of Sync word -VAL_SYNCVALUE1OOK = 0x80 # 1nd byte of Sync word -VAL_PACKETCONFIG1FSK = 0xA2 # Variable length, Manchester coding, Addr must match NodeAddress -VAL_PACKETCONFIG1FSKNO = 0xA0 # Variable length, Manchester coding -VAL_PACKETCONFIG1OOK = 0 # Fixed length, no Manchester coding -VAL_PAYLOADLEN255 = 0xFF # max Length in RX, not used in Tx -VAL_PAYLOADLEN66 = 66 # max Length in RX, not used in Tx -VAL_PAYLOADLEN_OOK = (13 + 8 * 17) # Payload Length -VAL_NODEADDRESS01 = 0x01 # Node address used in address filtering -VAL_NODEADDRESS04 = 0x04 # Node address used in address filtering -VAL_FIFOTHRESH1 = 0x81 # Condition to start packet transmission: at least one byte in FIFO -VAL_FIFOTHRESH30 = 0x1E # Condition to start packet transmission: wait for 30 bytes in FIFO - - -#----- HOPERF RADIO INTERFACE ------------------------------------------------- - -def HRF_writereg(addr, data): - """Write an 8 bit value to a register""" - buf = [addr | MASK_WRITE_DATA, data] - spi.select() - spi.frame(buf) - spi.deselect() - - -def HRF_readreg(addr): - """Read an 8 bit value from a register""" - buf = [addr, 0x00] - spi.select() - res = spi.frame(buf) - spi.deselect() - #print(hex(res[1])) - return res[1] # all registers are 8 bit - - -def HRF_writefifo_burst(buf): - """Write all bytes in buf to the payload FIFO, in a single burst""" - # Don't modify buf, in case caller reuses it - txbuf = [ADDR_FIFO | MASK_WRITE_DATA] - for b in buf: - txbuf.append(b) - #print("write FIFO %s" % ashex(txbuf)) - - spi.select() - spi.frame(txbuf) - spi.deselect() - - -def HRF_readfifo_burst(): - """Read bytes from the payload FIFO using burst read""" - #first byte read is the length in remaining bytes - buf = [] - spi.select() - spi.frame([ADDR_FIFO]) - count = 1 # read at least the length byte - while count > 0: - rx = spi.frame([ADDR_FIFO]) - data = rx[0] - if len(buf) == 0: - count = data - else: - count -= 1 - buf.append(data) - spi.deselect() - trace("readfifo:" + str(ashex(buf))) - return buf - - -def HRF_checkreg(addr, mask, value): - """Check to see if a register matches a specific value or not""" - regval = HRF_readreg(addr) - #print("addr %d mask %d wanted %d actual %d" % (addr,mask,value,regval)) - return (regval & mask) == value - - -def HRF_pollreg(addr, mask, value): - """Poll a register until it meet some criteria""" - while not HRF_checkreg(addr, mask, value): - pass - - -def HRF_wait_ready(): - """Wait for HRF to be ready after last command""" - HRF_pollreg(ADDR_IRQFLAGS1, MASK_MODEREADY, MASK_MODEREADY) - - -def HRF_wait_txready(): - """Wait for HRF to be ready and ready for tx, after last command""" - trace("waiting for transmit ready...") - HRF_pollreg(ADDR_IRQFLAGS1, MASK_MODEREADY|MASK_TXREADY, MASK_MODEREADY|MASK_TXREADY) - trace("transmit ready") - - -def HRF_change_mode(mode): - HRF_writereg(ADDR_OPMODE, mode) - - -def HRF_clear_fifo(): - """Clear any data in the HRF payload FIFO by reading until empty""" - while (HRF_readreg(ADDR_IRQFLAGS2) & MASK_FIFONOTEMPTY) == MASK_FIFONOTEMPTY: - HRF_readreg(ADDR_FIFO) - - -def HRF_check_payload(): - """Check if there is a payload in the FIFO waiting to be processed""" - irqflags1 = HRF_readreg(ADDR_IRQFLAGS1) - irqflags2 = HRF_readreg(ADDR_IRQFLAGS2) - #trace("irq1 %s irq2 %s" % (hex(irqflags1), hex(irqflags2))) - - return (irqflags2 & MASK_PAYLOADRDY) == MASK_PAYLOADRDY - - -def HRF_receive_payload(): - """Receive the whole payload""" - return HRF_readfifo_burst() - - -def HRF_send_payload(payload): - trace("send_payload") - #trace("payload:%s" % ashex(payload)) - HRF_writefifo_burst(payload) - trace(" waiting for sent...") - HRF_pollreg(ADDR_IRQFLAGS2, MASK_PACKETSENT, MASK_PACKETSENT) - trace(" sent") - reg = HRF_readreg(ADDR_IRQFLAGS2) - trace(" irqflags2=%s" % hex(reg)) - if ((reg & MASK_FIFONOTEMPTY) != 0) or ((reg & MASK_FIFOOVERRUN) != 0): - warning("Failed to send payload to HRF") - - - -#----- ENERGENIE SPECIFIC CONFIGURATIONS -------------------------------------- - -config_FSK = [ - [ADDR_REGDATAMODUL, VAL_REGDATAMODUL_FSK], # modulation scheme FSK - [ADDR_FDEVMSB, VAL_FDEVMSB30], # frequency deviation 5kHz 0x0052 -> 30kHz 0x01EC - [ADDR_FDEVLSB, VAL_FDEVLSB30], # frequency deviation 5kHz 0x0052 -> 30kHz 0x01EC - [ADDR_FRMSB, VAL_FRMSB434], # carrier freq -> 434.3MHz 0x6C9333 - [ADDR_FRMID, VAL_FRMID434], # carrier freq -> 434.3MHz 0x6C9333 - [ADDR_FRLSB, VAL_FRLSB434], # carrier freq -> 434.3MHz 0x6C9333 - [ADDR_AFCCTRL, VAL_AFCCTRLS], # standard AFC routine - [ADDR_LNA, VAL_LNA50], # 200ohms, gain by AGC loop -> 50ohms - [ADDR_RXBW, VAL_RXBW60], # channel filter bandwidth 10kHz -> 60kHz page:26 - [ADDR_BITRATEMSB, 0x1A], # 4800b/s - [ADDR_BITRATELSB, 0x0B], # 4800b/s - #[ADDR_AFCFEI, VAL_AFCFEIRX], # AFC is performed each time rx mode is entered - #[ADDR_RSSITHRESH, VAL_RSSITHRESH220], # RSSI threshold 0xE4 -> 0xDC (220) - #[ADDR_PREAMBLELSB, VAL_PREAMBLELSB5], # preamble size LSB set to 5 - [ADDR_SYNCCONFIG, VAL_SYNCCONFIG2], # Size of the Synch word = 2 (SyncSize + 1) - [ADDR_SYNCVALUE1, VAL_SYNCVALUE1FSK], # 1st byte of Sync word - [ADDR_SYNCVALUE2, VAL_SYNCVALUE2FSK], # 2nd byte of Sync word - #[ADDR_PACKETCONFIG1, VAL_PACKETCONFIG1FSK], # Variable length, Manchester coding, Addr must match NodeAddress - [ADDR_PACKETCONFIG1, VAL_PACKETCONFIG1FSKNO], # Variable length, Manchester coding - [ADDR_PAYLOADLEN, VAL_PAYLOADLEN66], # max Length in RX, not used in Tx - #[ADDR_NODEADDRESS, VAL_NODEADDRESS01], # Node address used in address filtering - [ADDR_NODEADDRESS, 0x06], # Node address used in address filtering - [ADDR_FIFOTHRESH, VAL_FIFOTHRESH1], # Condition to start packet transmission: at least one byte in FIFO - [ADDR_OPMODE, MODE_RECEIVER] # Operating mode to Receiver -] - -config_OOK = [ - [ADDR_REGDATAMODUL, VAL_REGDATAMODUL_OOK], # modulation scheme OOK - [ADDR_FDEVMSB, 0], # frequency deviation -> 0kHz - [ADDR_FDEVLSB, 0], # frequency deviation -> 0kHz - [ADDR_FRMSB, VAL_FRMSB433], # carrier freq -> 433.92MHz 0x6C7AE1 - [ADDR_FRMID, VAL_FRMID433], # carrier freq -> 433.92MHz 0x6C7AE1 - [ADDR_FRLSB, VAL_FRLSB433], # carrier freq -> 433.92MHz 0x6C7AE1 - [ADDR_RXBW, VAL_RXBW120], # channel filter bandwidth 120kHz - [ADDR_BITRATEMSB, 0x40], # 1938b/s - [ADDR_BITRATELSB, 0x80], # 1938b/s - [ADDR_PREAMBLELSB, 0], # preamble size LSB 3 - [ADDR_SYNCCONFIG, VAL_SYNCCONFIG4], # Size of the Sync word = 4 (SyncSize + 1) - [ADDR_SYNCVALUE1, VAL_SYNCVALUE1OOK], # sync value 1 - [ADDR_SYNCVALUE2, 0], # sync value 2 - [ADDR_SYNCVALUE3, 0], # sync value 3 - [ADDR_SYNCVALUE4, 0], # sync value 4 - [ADDR_PACKETCONFIG1, VAL_PACKETCONFIG1OOK], # Fixed length, no Manchester coding, OOK - [ADDR_PAYLOADLEN, VAL_PAYLOADLEN_OOK], # Payload Length - [ADDR_FIFOTHRESH, VAL_FIFOTHRESH30], # Condition to start packet transmission: wait for 30 bytes in FIFO -] - - -def HRF_config(config): - """Load a table of configuration values into HRF registers""" - for cmd in config: - HRF_writereg(cmd[0], cmd[1]) - HRF_wait_ready() - - -#ORIGINAL C CODE -#void HRF_send_OOK_msg(uint8_t relayState) -#{ -# uint8_t buf[17]; -# uint8_t i; -# -# HRF_config_OOK(); -# -# buf[1] = 0x80; // Preambule 32b enclosed in sync words -# buf[2] = 0x00; -# buf[3] = 0x00; -# buf[4] = 0x00; -# -# for (i = 5; i <= 14; ++i){ -# buf[i] = 8 + (i&1) * 6 + 128 + (i&2) * 48; // address 20b * 4 = 10 Bytes -# } -# -# if (relayState == 1) -# { -# printf("relay ON\n\n"); -# buf[15] = 0xEE; // D0-high, D1-h // S1 on -# buf[16] = 0xEE; // D2-h, D3-h -# } -# else -# { -# printf("relay OFF\n\n"); -# buf[15] = 0xEE; // D0-high, D1-h // S1 off -# buf[16] = 0xE8; // D2-h, D3-l -# } -# -# HRF_wait_for (ADDR_IRQFLAGS1, MASK_MODEREADY | MASK_TXREADY, true); // wait for ModeReady + TX ready -# HRF_reg_Wn(buf + 4, 0, 12); // don't include sync word (4 bytes) into data buffer -# -# for (i = 0; i < 8; ++i) // Send the same message few more times -# { -# HRF_wait_for(ADDR_IRQFLAGS2, MASK_FIFOLEVEL, false); -# HRF_reg_Wn(buf, 0, 16); // with sync word -# } -# -# HRF_wait_for (ADDR_IRQFLAGS2, MASK_PACKETSENT, true); // wait for Packet sent -# HRF_assert_reg_val(ADDR_IRQFLAGS2, MASK_FIFONOTEMPTY | MASK_FIFOOVERRUN, false, "are all bytes sent?"); -# HRF_config_FSK(); -# HRF_wait_for (ADDR_IRQFLAGS1, MASK_MODEREADY, true); // wait for ModeReady -#} - - -def HRF_send_OOK_payload(payload): - """Send a payload multiple times""" - - p1 = [0x00] + payload - # This sync pattern does not match C code, but it works. - # The sync pattern from the C code does not work here - # Note that buf[0] in the C is undefined due to being uninitialised - #pn = [0x00,0x80,0x00,0x00,0x00] # from the C - # Currently there is no explanation for this. - pn = [0x80,0x80,0x80,0x80,0x80] + payload - - HRF_pollreg(ADDR_IRQFLAGS1, MASK_MODEREADY|MASK_TXREADY, MASK_MODEREADY|MASK_TXREADY) - HRF_writefifo_burst(p1) - - for i in range(8): - HRF_pollreg(ADDR_IRQFLAGS2, MASK_FIFOLEVEL, 0) - HRF_writefifo_burst(pn) - - HRF_pollreg(ADDR_IRQFLAGS2, MASK_PACKETSENT, MASK_PACKETSENT) # wait for Packet sent - - reg = HRF_readreg(ADDR_IRQFLAGS2) - #trace(" irqflags2=%s" % hex(reg)) - if (reg & (MASK_FIFONOTEMPTY) != 0) or ((reg & MASK_FIFOOVERRUN) != 0): - warning("Failed to send repeated payload to HRF") - - - -#----- RADIO API -------------------------------------------------------------- - -mode = None -modulation_fsk = None - -def init(): - """Initialise the module ready for use""" - spi.init_defaults() - trace("RESET") - - # Note that if another program left GPIO pins in a different state - # and did a dirty exit, the reset fails to work and the clear fifo hangs. - # Might have to make the spi.init() set everything to inputs first, - # then set to outputs, to make sure that the - # GPIO registers are in a deterministic start state. - spi.reset() # send a hardware reset to ensure radio in clean state - - HRF_clear_fifo() - - -def modulation(fsk=None, ook=None): - """Switch modulation, if needed""" - global modulation_fsk - - # Handle sensible module defaults for earlier versions of user code - if fsk == None and ook == None: - # Force FSK mode - fsk = True - - if fsk != None and fsk: - if modulation_fsk == None or modulation_fsk == False: - trace("switch to FSK") - HRF_config(config_FSK) - modulation_fsk = True - - elif ook != None and ook: - if modulation_fsk == None or modulation_fsk == True: - trace("switch to OOK") - HRF_config(config_OOK) - modulation_fsk = False - - -def transmitter(fsk=None, ook=None): - """Change into transmitter mode""" - global mode - - trace("transmitter mode") - modulation(fsk, ook) - HRF_change_mode(MODE_TRANSMITER) - mode = "TRANSMITTER" - HRF_wait_txready() - - -def transmit(payload): - """Transmit a single payload using the present modulation scheme""" - if not modulation_fsk: - HRF_send_OOK_payload(payload) - else: - HRF_send_payload(payload) - - -def receiver(fsk=None, ook=None): - """Change into receiver mode""" - global mode - - trace("receiver mode") - modulation(fsk, ook) - HRF_change_mode(MODE_RECEIVER) - HRF_wait_ready() - mode = "RECEIVER" - - -def isReceiveWaiting(): - """Check to see if a payload is waiting in the receive buffer""" - return HRF_check_payload() - - -def receive(): - """Receive a single payload from the buffer using the present modulation scheme""" - return HRF_receive_payload() - - -def finished(): - """Close the library down cleanly when finished""" - spi.finished() - - -# END +// # test1.py 26/09/2015 D.J.Whale +// # +// # Simple low level test of the HopeRF interface +// # Uses direct SPI commands to exercise the interface. +// # +// # Receives and dumps payload buffers. +// # +// # Eventually a lot of this will be pushed into a separate module, +// # and then pushed back into C once it is proved working. +// // +// import spi +// // +// def warning(msg): +// print("warning:" + str(msg)) +// // +// def trace(msg): +// print(str(msg)) +// // +// +// def ashex(p): +// line = "" +// for b in p: +// line += str(hex(b)) + " " +// return line +// // +// +// #----- HOPERF REGISTER INTERFACE ---------------------------------------------- +// # Precise register descriptions can be found in: +// # www.hoperf.com/upload/rf/RFM69W-V1.3.pdf +// # on page 63 - 74 +// // +// ADDR_FIFO = 0x00 +// ADDR_OPMODE = 0x01 +// ADDR_REGDATAMODUL = 0x02 +// ADDR_BITRATEMSB = 0x03 +// ADDR_BITRATELSB = 0x04 +// ADDR_FDEVMSB = 0x05 +// ADDR_FDEVLSB = 0x06 +// ADDR_FRMSB = 0x07 +// ADDR_FRMID = 0x08 +// ADDR_FRLSB = 0x09 +// ADDR_AFCCTRL = 0x0B +// ADDR_LNA = 0x18 +// ADDR_RXBW = 0x19 +// ADDR_AFCFEI = 0x1E +// ADDR_IRQFLAGS1 = 0x27 +// ADDR_IRQFLAGS2 = 0x28 +// ADDR_RSSITHRESH = 0x29 +// ADDR_PREAMBLELSB = 0x2D +// ADDR_SYNCCONFIG = 0x2E +// ADDR_SYNCVALUE1 = 0x2F +// ADDR_SYNCVALUE2 = 0x30 +// ADDR_SYNCVALUE3 = 0x31 +// ADDR_SYNCVALUE4 = 0x32 +// ADDR_PACKETCONFIG1 = 0x37 +// ADDR_PAYLOADLEN = 0x38 +// ADDR_NODEADDRESS = 0x39 +// ADDR_FIFOTHRESH = 0x3C +// // +// # HopeRF masks to set and clear bits +// MASK_REGDATAMODUL_OOK = 0x08 +// MASK_REGDATAMODUL_FSK = 0x00 +// MASK_WRITE_DATA = 0x80 +// MASK_MODEREADY = 0x80 +// MASK_FIFONOTEMPTY = 0x40 +// MASK_FIFOLEVEL = 0x20 +// MASK_FIFOOVERRUN = 0x10 +// MASK_PACKETSENT = 0x08 +// MASK_TXREADY = 0x20 +// MASK_PACKETMODE = 0x60 +// MASK_MODULATION = 0x18 +// MASK_PAYLOADRDY = 0x04 +// // +// MODE_STANDBY = 0x04 # Standby +// MODE_TRANSMITER = 0x0C # Transmiter +// MODE_RECEIVER = 0x10 # Receiver +// VAL_REGDATAMODUL_FSK = 0x00 # Modulation scheme FSK +// VAL_REGDATAMODUL_OOK = 0x08 # Modulation scheme OOK +// VAL_FDEVMSB30 = 0x01 # frequency deviation 5kHz 0x0052 -> 30kHz 0x01EC +// VAL_FDEVLSB30 = 0xEC # frequency deviation 5kHz 0x0052 -> 30kHz 0x01EC +// VAL_FRMSB434 = 0x6C # carrier freq -> 434.3MHz 0x6C9333 +// VAL_FRMID434 = 0x93 # carrier freq -> 434.3MHz 0x6C9333 +// VAL_FRLSB434 = 0x33 # carrier freq -> 434.3MHz 0x6C9333 +// VAL_FRMSB433 = 0x6C # carrier freq -> 433.92MHz 0x6C7AE1 +// VAL_FRMID433 = 0x7A # carrier freq -> 433.92MHz 0x6C7AE1 +// VAL_FRLSB433 = 0xE1 # carrier freq -> 433.92MHz 0x6C7AE1 +// VAL_AFCCTRLS = 0x00 # standard AFC routine +// VAL_AFCCTRLI = 0x20 # improved AFC routine +// VAL_LNA50 = 0x08 # LNA input impedance 50 ohms +// VAL_LNA50G = 0x0E # LNA input impedance 50 ohms, LNA gain -> 48db +// VAL_LNA200 = 0x88 # LNA input impedance 200 ohms +// VAL_RXBW60 = 0x43 # channel filter bandwidth 10kHz -> 60kHz page:26 +// VAL_RXBW120 = 0x41 # channel filter bandwidth 120kHz +// VAL_AFCFEIRX = 0x04 # AFC is performed each time RX mode is entered +// VAL_RSSITHRESH220 = 0xDC # RSSI threshold 0xE4 -> 0xDC (220) +// VAL_PREAMBLELSB3 = 0x03 # preamble size LSB 3 +// VAL_PREAMBLELSB5 = 0x05 # preamble size LSB 5 +// VAL_SYNCCONFIG2 = 0x88 # Size of the Synch word = 2 (SyncSize + 1) +// VAL_SYNCCONFIG4 = 0x98 # Size of the Synch word = 4 (SyncSize + 1) +// VAL_SYNCVALUE1FSK = 0x2D # 1st byte of Sync word +// VAL_SYNCVALUE2FSK = 0xD4 # 2nd byte of Sync word +// VAL_SYNCVALUE1OOK = 0x80 # 1nd byte of Sync word +// VAL_PACKETCONFIG1FSK = 0xA2 # Variable length, Manchester coding, Addr must match NodeAddress +// VAL_PACKETCONFIG1FSKNO = 0xA0 # Variable length, Manchester coding +// VAL_PACKETCONFIG1OOK = 0 # Fixed length, no Manchester coding +// VAL_PAYLOADLEN255 = 0xFF # max Length in RX, not used in Tx +// VAL_PAYLOADLEN66 = 66 # max Length in RX, not used in Tx +// VAL_PAYLOADLEN_OOK = (13 + 8 * 17) # Payload Length +// VAL_NODEADDRESS01 = 0x01 # Node address used in address filtering +// VAL_NODEADDRESS04 = 0x04 # Node address used in address filtering +// VAL_FIFOTHRESH1 = 0x81 # Condition to start packet transmission: at least one byte in FIFO +// VAL_FIFOTHRESH30 = 0x1E # Condition to start packet transmission: wait for 30 bytes in FIFO +// // +// +// #----- HOPERF RADIO INTERFACE ------------------------------------------------- +// // +// def HRF_writereg(addr, data): +// """Write an 8 bit value to a register""" +// buf = [addr | MASK_WRITE_DATA, data] +// spi.select() +// spi.frame(buf) +// spi.deselect() +// // +// +// def HRF_readreg(addr): +// """Read an 8 bit value from a register""" +// buf = [addr, 0x00] +// spi.select() +// res = spi.frame(buf) +// spi.deselect() +// #print(hex(res[1])) +// return res[1] # all registers are 8 bit +// // +// +// def HRF_writefifo_burst(buf): +// """Write all bytes in buf to the payload FIFO, in a single burst""" +// # Don't modify buf, in case caller reuses it +// txbuf = [ADDR_FIFO | MASK_WRITE_DATA] +// for b in buf: +// txbuf.append(b) +// #print("write FIFO %s" % ashex(txbuf)) +// // +// spi.select() +// spi.frame(txbuf) +// spi.deselect() +// // +// +// def HRF_readfifo_burst(): +// """Read bytes from the payload FIFO using burst read""" +// #first byte read is the length in remaining bytes +// buf = [] +// spi.select() +// spi.frame([ADDR_FIFO]) +// count = 1 # read at least the length byte +// while count > 0: +// rx = spi.frame([ADDR_FIFO]) +// data = rx[0] +// if len(buf) == 0: +// count = data +// else: +// count -= 1 +// buf.append(data) +// spi.deselect() +// trace("readfifo:" + str(ashex(buf))) +// return buf +// // +// +// def HRF_checkreg(addr, mask, value): +// """Check to see if a register matches a specific value or not""" +// regval = HRF_readreg(addr) +// #print("addr %d mask %d wanted %d actual %d" % (addr,mask,value,regval)) +// return (regval & mask) == value +// // +// +// def HRF_pollreg(addr, mask, value): +// """Poll a register until it meet some criteria""" +// while not HRF_checkreg(addr, mask, value): +// pass +// // +// +// def HRF_wait_ready(): +// """Wait for HRF to be ready after last command""" +// HRF_pollreg(ADDR_IRQFLAGS1, MASK_MODEREADY, MASK_MODEREADY) +// // +// +// def HRF_wait_txready(): +// """Wait for HRF to be ready and ready for tx, after last command""" +// trace("waiting for transmit ready...") +// HRF_pollreg(ADDR_IRQFLAGS1, MASK_MODEREADY|MASK_TXREADY, MASK_MODEREADY|MASK_TXREADY) +// trace("transmit ready") +// // +// +// def HRF_change_mode(mode): +// HRF_writereg(ADDR_OPMODE, mode) +// // +// +// def HRF_clear_fifo(): +// """Clear any data in the HRF payload FIFO by reading until empty""" +// while (HRF_readreg(ADDR_IRQFLAGS2) & MASK_FIFONOTEMPTY) == MASK_FIFONOTEMPTY: +// HRF_readreg(ADDR_FIFO) +// // +// +// def HRF_check_payload(): +// """Check if there is a payload in the FIFO waiting to be processed""" +// irqflags1 = HRF_readreg(ADDR_IRQFLAGS1) +// irqflags2 = HRF_readreg(ADDR_IRQFLAGS2) +// #trace("irq1 %s irq2 %s" % (hex(irqflags1), hex(irqflags2))) +// // +// return (irqflags2 & MASK_PAYLOADRDY) == MASK_PAYLOADRDY +// // +// +// def HRF_receive_payload(): +// """Receive the whole payload""" +// return HRF_readfifo_burst() +// // +// +// def HRF_send_payload(payload): +// trace("send_payload") +// #trace("payload:%s" % ashex(payload)) +// HRF_writefifo_burst(payload) +// trace(" waiting for sent...") +// HRF_pollreg(ADDR_IRQFLAGS2, MASK_PACKETSENT, MASK_PACKETSENT) +// trace(" sent") +// reg = HRF_readreg(ADDR_IRQFLAGS2) +// trace(" irqflags2=%s" % hex(reg)) +// if ((reg & MASK_FIFONOTEMPTY) != 0) or ((reg & MASK_FIFOOVERRUN) != 0): +// warning("Failed to send payload to HRF") +// // +// +// +// #----- ENERGENIE SPECIFIC CONFIGURATIONS -------------------------------------- +// // +// config_FSK = [ +// [ADDR_REGDATAMODUL, VAL_REGDATAMODUL_FSK], # modulation scheme FSK +// [ADDR_FDEVMSB, VAL_FDEVMSB30], # frequency deviation 5kHz 0x0052 -> 30kHz 0x01EC +// [ADDR_FDEVLSB, VAL_FDEVLSB30], # frequency deviation 5kHz 0x0052 -> 30kHz 0x01EC +// [ADDR_FRMSB, VAL_FRMSB434], # carrier freq -> 434.3MHz 0x6C9333 +// [ADDR_FRMID, VAL_FRMID434], # carrier freq -> 434.3MHz 0x6C9333 +// [ADDR_FRLSB, VAL_FRLSB434], # carrier freq -> 434.3MHz 0x6C9333 +// [ADDR_AFCCTRL, VAL_AFCCTRLS], # standard AFC routine +// [ADDR_LNA, VAL_LNA50], # 200ohms, gain by AGC loop -> 50ohms +// [ADDR_RXBW, VAL_RXBW60], # channel filter bandwidth 10kHz -> 60kHz page:26 +// [ADDR_BITRATEMSB, 0x1A], # 4800b/s +// [ADDR_BITRATELSB, 0x0B], # 4800b/s +// #[ADDR_AFCFEI, VAL_AFCFEIRX], # AFC is performed each time rx mode is entered +// #[ADDR_RSSITHRESH, VAL_RSSITHRESH220], # RSSI threshold 0xE4 -> 0xDC (220) +// #[ADDR_PREAMBLELSB, VAL_PREAMBLELSB5], # preamble size LSB set to 5 +// [ADDR_SYNCCONFIG, VAL_SYNCCONFIG2], # Size of the Synch word = 2 (SyncSize + 1) +// [ADDR_SYNCVALUE1, VAL_SYNCVALUE1FSK], # 1st byte of Sync word +// [ADDR_SYNCVALUE2, VAL_SYNCVALUE2FSK], # 2nd byte of Sync word +// #[ADDR_PACKETCONFIG1, VAL_PACKETCONFIG1FSK], # Variable length, Manchester coding, Addr must match NodeAddress +// [ADDR_PACKETCONFIG1, VAL_PACKETCONFIG1FSKNO], # Variable length, Manchester coding +// [ADDR_PAYLOADLEN, VAL_PAYLOADLEN66], # max Length in RX, not used in Tx +// #[ADDR_NODEADDRESS, VAL_NODEADDRESS01], # Node address used in address filtering +// [ADDR_NODEADDRESS, 0x06], # Node address used in address filtering +// [ADDR_FIFOTHRESH, VAL_FIFOTHRESH1], # Condition to start packet transmission: at least one byte in FIFO +// [ADDR_OPMODE, MODE_RECEIVER] # Operating mode to Receiver +// ] +// // +// config_OOK = [ +// [ADDR_REGDATAMODUL, VAL_REGDATAMODUL_OOK], # modulation scheme OOK +// [ADDR_FDEVMSB, 0], # frequency deviation -> 0kHz +// [ADDR_FDEVLSB, 0], # frequency deviation -> 0kHz +// [ADDR_FRMSB, VAL_FRMSB433], # carrier freq -> 433.92MHz 0x6C7AE1 +// [ADDR_FRMID, VAL_FRMID433], # carrier freq -> 433.92MHz 0x6C7AE1 +// [ADDR_FRLSB, VAL_FRLSB433], # carrier freq -> 433.92MHz 0x6C7AE1 +// [ADDR_RXBW, VAL_RXBW120], # channel filter bandwidth 120kHz +// [ADDR_BITRATEMSB, 0x40], # 1938b/s +// [ADDR_BITRATELSB, 0x80], # 1938b/s +// [ADDR_PREAMBLELSB, 0], # preamble size LSB 3 +// [ADDR_SYNCCONFIG, VAL_SYNCCONFIG4], # Size of the Sync word = 4 (SyncSize + 1) +// [ADDR_SYNCVALUE1, VAL_SYNCVALUE1OOK], # sync value 1 +// [ADDR_SYNCVALUE2, 0], # sync value 2 +// [ADDR_SYNCVALUE3, 0], # sync value 3 +// [ADDR_SYNCVALUE4, 0], # sync value 4 +// [ADDR_PACKETCONFIG1, VAL_PACKETCONFIG1OOK], # Fixed length, no Manchester coding, OOK +// [ADDR_PAYLOADLEN, VAL_PAYLOADLEN_OOK], # Payload Length +// [ADDR_FIFOTHRESH, VAL_FIFOTHRESH30], # Condition to start packet transmission: wait for 30 bytes in FIFO +// ] +// // +// +// def HRF_config(config): +// """Load a table of configuration values into HRF registers""" +// for cmd in config: +// HRF_writereg(cmd[0], cmd[1]) +// HRF_wait_ready() +// // +// +// #ORIGINAL C CODE +// #void HRF_send_OOK_msg(uint8_t relayState) +// #{ +// # uint8_t buf[17]; +// # uint8_t i; +// # +// # HRF_config_OOK(); +// # +// # buf[1] = 0x80; // Preambule 32b enclosed in sync words +// # buf[2] = 0x00; +// # buf[3] = 0x00; +// # buf[4] = 0x00; +// # +// # for (i = 5; i <= 14; ++i){ +// # buf[i] = 8 + (i&1) * 6 + 128 + (i&2) * 48; // address 20b * 4 = 10 Bytes +// # } +// # +// # if (relayState == 1) +// # { +// # printf("relay ON\n\n"); +// # buf[15] = 0xEE; // D0-high, D1-h // S1 on +// # buf[16] = 0xEE; // D2-h, D3-h +// # } +// # else +// # { +// # printf("relay OFF\n\n"); +// # buf[15] = 0xEE; // D0-high, D1-h // S1 off +// # buf[16] = 0xE8; // D2-h, D3-l +// # } +// # +// # HRF_wait_for (ADDR_IRQFLAGS1, MASK_MODEREADY | MASK_TXREADY, true); // wait for ModeReady + TX ready +// # HRF_reg_Wn(buf + 4, 0, 12); // don't include sync word (4 bytes) into data buffer +// # +// # for (i = 0; i < 8; ++i) // Send the same message few more times +// # { +// # HRF_wait_for(ADDR_IRQFLAGS2, MASK_FIFOLEVEL, false); +// # HRF_reg_Wn(buf, 0, 16); // with sync word +// # } +// # +// # HRF_wait_for (ADDR_IRQFLAGS2, MASK_PACKETSENT, true); // wait for Packet sent +// # HRF_assert_reg_val(ADDR_IRQFLAGS2, MASK_FIFONOTEMPTY | MASK_FIFOOVERRUN, false, "are all bytes sent?"); +// # HRF_config_FSK(); +// # HRF_wait_for (ADDR_IRQFLAGS1, MASK_MODEREADY, true); // wait for ModeReady +// #} +// // +// +// def HRF_send_OOK_payload(payload): +// """Send a payload multiple times""" +// // +// p1 = [0x00] + payload +// # This sync pattern does not match C code, but it works. +// # The sync pattern from the C code does not work here +// # Note that buf[0] in the C is undefined due to being uninitialised +// #pn = [0x00,0x80,0x00,0x00,0x00] # from the C +// # Currently there is no explanation for this. +// pn = [0x80,0x80,0x80,0x80,0x80] + payload +// // +// HRF_pollreg(ADDR_IRQFLAGS1, MASK_MODEREADY|MASK_TXREADY, MASK_MODEREADY|MASK_TXREADY) +// HRF_writefifo_burst(p1) +// +// for i in range(8): +// HRF_pollreg(ADDR_IRQFLAGS2, MASK_FIFOLEVEL, 0) +// HRF_writefifo_burst(pn) +// // +// HRF_pollreg(ADDR_IRQFLAGS2, MASK_PACKETSENT, MASK_PACKETSENT) # wait for Packet sent +// // +// reg = HRF_readreg(ADDR_IRQFLAGS2) +// #trace(" irqflags2=%s" % hex(reg)) +// if (reg & (MASK_FIFONOTEMPTY) != 0) or ((reg & MASK_FIFOOVERRUN) != 0): +// warning("Failed to send repeated payload to HRF") +// // +// +// +// #----- RADIO API -------------------------------------------------------------- +// // +// mode = None +// modulation_fsk = None +// // +// def init(): +// """Initialise the module ready for use""" +// spi.init_defaults() +// trace("RESET") +// // +// # Note that if another program left GPIO pins in a different state +// # and did a dirty exit, the reset fails to work and the clear fifo hangs. +// # Might have to make the spi.init() set everything to inputs first, +// # then set to outputs, to make sure that the +// # GPIO registers are in a deterministic start state. +// spi.reset() # send a hardware reset to ensure radio in clean state +// // +// HRF_clear_fifo() +// // +// +// def modulation(fsk=None, ook=None): +// """Switch modulation, if needed""" +// global modulation_fsk +// // +// # Handle sensible module defaults for earlier versions of user code +// if fsk == None and ook == None: +// # Force FSK mode +// fsk = True +// // +// if fsk != None and fsk: +// if modulation_fsk == None or modulation_fsk == False: +// trace("switch to FSK") +// HRF_config(config_FSK) +// modulation_fsk = True +// // +// elif ook != None and ook: +// if modulation_fsk == None or modulation_fsk == True: +// trace("switch to OOK") +// HRF_config(config_OOK) +// modulation_fsk = False +// // +// +// def transmitter(fsk=None, ook=None): +// """Change into transmitter mode""" +// global mode +// // +// trace("transmitter mode") +// modulation(fsk, ook) +// HRF_change_mode(MODE_TRANSMITER) +// mode = "TRANSMITTER" +// HRF_wait_txready() +// // +// +// def transmit(payload): +// """Transmit a single payload using the present modulation scheme""" +// if not modulation_fsk: +// HRF_send_OOK_payload(payload) +// else: +// HRF_send_payload(payload) +// // +// +// def receiver(fsk=None, ook=None): +// """Change into receiver mode""" +// global mode +// // +// trace("receiver mode") +// modulation(fsk, ook) +// HRF_change_mode(MODE_RECEIVER) +// HRF_wait_ready() +// mode = "RECEIVER" +// // +// +// def isReceiveWaiting(): +// """Check to see if a payload is waiting in the receive buffer""" +// return HRF_check_payload() +// // +// +// def receive(): +// """Receive a single payload from the buffer using the present modulation scheme""" +// return HRF_receive_payload() +// // +// +// def finished(): +// """Close the library down cleanly when finished""" +// spi.finished() +// // +// +// # END diff --git a/src/energenie/drv/spi_test.c b/src/energenie/drv/spi_test.c index 56f44ca..2962476 100644 --- a/src/energenie/drv/spi_test.c +++ b/src/energenie/drv/spi_test.c @@ -14,8 +14,8 @@ #include "system.h" #include "gpio.h" #include "spi.h" +#include "trace.h" -//TODO: printfs will not work on Arduino /***** CONSTANTS *****/ @@ -46,21 +46,28 @@ /* Init */ - printf("init\n"); + + //printf("init\n"); + TRACE_OUTS("init"); + TRACE_NL(); //gpio_init(); done by spi_init() spi_init(&spiConfig); /* Enter programming mode */ - printf("select\n"); + //printf("select\n"); + TRACE_OUTS("select"); + TRACE_NL(); spi_select(); spi_frame(cmd_prog, NULL, 4); /* Get ID bytes */ - printf("read ID bytes\n"); + //printf("read ID bytes\n"); + TRACE_OUTS("read ID bytes"); + TRACE_NL(); spi_frame(cmd_id0, rx, 4); id[0] = rx[3]; @@ -75,7 +82,14 @@ /* Show ID bytes */ - printf("ID: %02X %02X %02X\n", id[0], id[1], id[2]); + //printf("ID: %02X %02X %02X\n", id[0], id[1], id[2]); + TRACE_OUTS("ID: "); + for (int i=0; i<3; i++) + { + TRACE_OUTN(id[0]); + TRACE_OUTC(' '); + } + TRACE_NL(); spi_finished(); return 0; diff --git a/src/energenie/drv/spis.c b/src/energenie/drv/spis.c index 5e05a0c..ceb2198 100644 --- a/src/energenie/drv/spis.c +++ b/src/energenie/drv/spis.c @@ -14,6 +14,7 @@ #include "spi.h" #include "gpio.h" #include "delay.h" +#include "trace.h" /***** MACROS *****/ @@ -24,12 +25,6 @@ #define SELECTED() gpio_write(config.cs, config.spol?1:0) #define NOT_SELECTED() gpio_write(config.cs, config.spol?0:1) -//TODO: Posix specific, won't work on Arduino -#define FAIL(msg) do { \ - fprintf(stderr, "%s", msg); \ - exit(-1); \ -} while (0) - /***** VARIABLES *****/ @@ -64,7 +59,7 @@ //TODO: Implement CPHA1 if (config.cpha != 0) { - FAIL("error: CPHA 1 not yet supported"); + TRACE_FAIL("error: CPHA 1 not yet supported"); } gpio_setout(config.sclk); diff --git a/src/energenie/drv/trace.c b/src/energenie/drv/trace.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/energenie/drv/trace.c diff --git a/src/energenie/drv/trace.h b/src/energenie/drv/trace.h new file mode 100644 index 0000000..65118c6 --- /dev/null +++ b/src/energenie/drv/trace.h @@ -0,0 +1,34 @@ +/* trace.h 04/04/2016 D.J.Whale + * + * Simple trace output. + * + * On some platforms this is just printf. + * On others it might write to a serial port + * On others it might write to a trace buffer viewed in an emulator + * It could be configured to do nothing. + */ + +#ifndef _TRACE_H +#define _TRACE_H + +/* POSIX IMPLEMENTATION */ +/* Printf is not available on some platforms, or not very efficient. + * These macros make it possible to re-map I/O to more efficient functions. + */ + +#include + +#define TRACE_OUTS(s) printf("%s", s) +#define TRACE_OUTN(n) printf("%d", (unsigned int)n) +#define TRACE_OUTC(c) putc(c, stdout) +#define TRACE_NL() TRACE_OUTC('\n') + +#define TRACE_FAIL(msg) do { \ + fprintf(stderr, "%s", msg); \ + exit(-1); \ +} while (0) + +#endif + +/***** END OF FILE *****/ +