# ############################################################################# # # Copyright (c) 1999-2001 by Wayne C. Gramlich. # All rights reserved. # # Permission to use, copy, modify, distribute, and sell this software # for any purpose is hereby granted without fee provided that the above # copyright notice and this permission are retained. The author makes # no representations about the suitability of this software for any purpose. # It is provided "as is" without express or implied warranty. # # This is a test harness for developing Robobricks. Basically it allows # the user to type in an 8-bit number in octal and send it to a RoboBrick. # Any resulting data is read back and printed in octal. All communication # occurs at 2400 baud. See # # http://web.gramlich.net/projects/robobricks/harness/index.html # # for more details. # # ############################################################################# processor pic16f84 cp=off dp=off pwrte=disabled wdte=disabled fosc=xt constant clock_rate 4000000 constant instruction_rate clock_rate / 4 constant baud_rate 2400 constant instructions_per_bit instruction_rate / baud_rate constant delays_per_bit 3 constant instructions_per_delay instructions_per_bit / delays_per_bit constant delay_count instructions_per_delay / 6 constant sp 32 constant cr 13 constant lf 10 # Some bit definitions: constant rx_slave_bit 0 constant tx_slave_bit 1 constant tx_master_bit 2 constant rx_master_bit 3 constant rx_slave_mask 1 << rx_slave_bit constant tx_slave_mask 1 << tx_slave_bit constant rx_master_mask 1 << rx_master_bit constant tx_master_mask 1 << tx_master_bit port porta a bits_only read_write_static pin tx_master_pin porta tx_master_bit write_only pin rx_master_pin porta rx_master_bit read_only pin tx_slave_pin porta tx_slave_bit write_only pin rx_slave_pin porta rx_slave_bit read_only pin heart porta 4 write_only port portb b unused none constant space 0xff constant buffer_size 5 string_constants { hello = 0s'Harness-A', cr, lf } procedure main { arguments_none returns_nothing # Read a byte. variable char byte variable number byte variable count byte variable index byte variable buffer[buffer_size] byte # Let all the capacitors charge up: count_down index 250 { call delay() } # Print out a welcome message: index := 0 while (index < hello.size) { char := hello[index] call master_send(char, tx_master_mask) index := index + 1 } # Main loop number := 0 loop_forever { # Get a character: tx_slave_pin := 1 char := master_get() # Delay 2/3's of bit make sure that get_byte is done. call delay() call delay() if (0c'0' <= char && char < (0c'9' + 1)) { # Do a multiply by 8 then add in digit: call master_send(char) number := (number << 3) + char - 0c'0' } else_if (char = 0c's') { # Send byte to brick, no wait: # Echo command and send CRLF: call master_send(char) call master_crlf() # Ship the byte down to the brick: call slave_send(number) number := 0 } else_if (char = 0c'w') { # Send byte to brick, wait for results: # Echo command and send CRLF: call master_send(char) call master_crlf() # Ship the byte down to the brick ... call slave_send(number) number := 0 #call delay() # ...and wait for a response: index := 0 while (index < buffer_size) { buffer[index] := slave_get() index := index + 1 } index := 0 while (index < buffer_size) { call master_octal(buffer[index]) index := index + 1 } # Terminate the output list call master_crlf() } else_if (char = 0c'i') { # Interrogate the slave RoboBrick: # Initialize the id index: call slave_send(0xfd) # Get the first 8 bytes: call slave_id8() # Get the next 8 bytes of random numbers: call slave_id8() # Get the next 8 bytes of random numbers: call slave_id8() # Get the slave brick name: call slave_id_string() # Get the vendor name: call slave_id_string() } else_if (char != 0xfc) { # Just echo back the current number: call master_send(0c'<') call master_octal(char) call master_send(0c'>') # Send a carriage-return line-feed: call master_crlf() # Output the character in octal: call master_octal(number) # Send a carriage-return line-feed: call master_crlf() # Reset number number := 0 } } } procedure master_crlf { arguments_none returns_nothing # This procedure will output a carriage-return line-feed # to the master. call master_send(cr) call master_send(lf) } procedure master_get { arguments_none returns byte # This procedure will get the next byte or return 0xfc if # no byte is forthcoming. return get_byte(rx_master_mask) } procedure master_send { argument character byte returns_nothing # This procedure will output {character} to the master. call send_byte(character, tx_master_mask) } procedure master_octal { argument number byte returns_nothing # This procedure will output {number} in octal to the tx port. # Output the character in octal: call master_send((number>>6) + 0c'0') call master_send(((number>>3) & 7) + 0c'0') call master_send((number & 7) + 0c'0') call master_send(sp) } procedure slave_get { arguments_none returns byte # This procedure will get a byte from the slave or return 0xfc # if no byte is forthcoming. return get_byte(rx_slave_mask) } procedure slave_id8 { arguments_none returns_nothing # This procedure will print out the next 8 bytes of data from # the slave RoboBrick id bytes. variable counter byte count_down counter 8 { call master_octal(slave_id_next()) } call master_crlf() } procedure slave_id_next { arguments_none returns byte # This procedure will return the next byte from the id bytes. call slave_send(0xfc) return slave_get() } procedure slave_id_string { arguments_none returns_nothing # This procedure will return the string for the id bytes. variable size byte size := slave_id_next() call master_octal(size) count_down size size { call master_send(slave_id_next()) } call master_crlf() } procedure slave_send { argument data byte returns_nothing # This procedure will send one byte of {data} to the slave. call send_byte(data, tx_slave_mask) } procedure get_byte { argument mask byte returns byte # Get an 8-bit byte from {mask} bit of {porta} and return it. # If no character shows up in a while 0xfc is returned. variable count byte variable char byte # Wait until a start bit arrives: count := 0 while (porta & mask != 0) { count := count - 1 if (count = 0) { return 0xfc } call delay() } # Skip over the start bit: call delay() call delay() call delay() # Sample in the middle third of each data bit: char := 0 count_down count 8 { call delay() char := char >> 1 if (porta & mask != 0) { #char := char | 0x80 char@7 := 1 } call delay() call delay() } # Skip over 1/3 of the stop bit: call delay() return char } procedure send_byte { argument char byte argument mask byte returns_nothing # Send {char} to {mask} bit of {porta}. variable count byte variable mark byte # Send the start bit: mark := mask ^ space porta := mark call delay() call delay() call delay() # Send the data: count_down count 8 { if (char@0) { porta := space } else { porta := mark } char := char >> 1 call delay() call delay() call delay() } # Send the stop bit: porta := space call delay() call delay() call delay() } procedure delay { arguments_none returns_nothing uniform_delay instructions_per_delay # Delay 1 third of a bit: }