# ############################################################################# # # Copyright (c) 2000-2001 by Wayne C. Gramlich and Bill Benson # 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 the code that implements the Activity9 RoboBrick. Basically # it just waits for commands that come in at 2400 baud and responds # to them. See: # # http://web.gramlich.net/projects/robobricks/activity9/index.html # # for more details. # # ############################################################################# processor pic16c505 cp=off wdte=on mclre=off fosc=intrc_no_clock # Define processor constants: constant clock_rate 4000000 constant clocks_per_instruction 4 constant instruction_rate clock_rate / clocks_per_instruction # Define serial communication control constants: 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 extra_instructions_per_bit 2 constant extra_instructions_per_delay extra_instructions_per_bit / delays_per_bit constant delay_instructions instructions_per_delay - extra_instructions_per_delay # Extra constants: constant bits_per_character 1 + 8 + 1 constant delays_per_character bits_per_character * delays_per_bit constant delay_count delays_per_character - 1 # LED Bindings: # S2M0 = D1 = RB0 # S2M1 = D2 = RB1 # S2M2 = D3 = RB2 # S2M3 = D4 = RB4 # M2S0 = D5 = RC0 # M2S1 = D6 = RC1 # M2S2 = D7 = RC2 # M2S3 = D8 = RC3 # INT = D9 = RC4 # Define pin assignments and directions: port portb b bits_and_byte read_write_static port portc c bits_and_byte read_write_static pin s2mled0 portb 0 write_only pin s2mled1 portb 1 write_only pin s2mled2 portb 2 write_only pin master_serial_in portb 3 read_only pin s2mled3 portb 4 write_only pin slave_serial_in portb 5 read_only pin m2sled0 portc 0 write_only pin m2sled1 portc 1 write_only pin m2sled2 portc 2 write_only pin m2sled3 portc 3 write_only pin intled portc 4 write_only pin switch portc 5 read_only # Global variables go here: global m2s_counter byte global master_delay byte global s2m_counter byte global slave_delay byte global debounce_counter byte procedure main { arguments_none returns_nothing # Initialize: m2s_counter := 0 master_delay := 0 s2m_counter := 0 slave_delay := 0 # Wait for data to fly by: loop_forever { call delay() } } procedure delay { arguments_none returns_nothing uniform_delay delay_instructions # Delay 1/3 of a bit: #FIXME: Code genearte for "m2sled0 := !m2s_counter@0" broken!!! if (switch) { # Show most significant bits of master to slave counter: if (m2s_counter@4) { m2sled0 := 0 } else { m2sled0 := 1 } if (m2s_counter@5) { m2sled1 := 0 } else { m2sled1 := 1 } if (m2s_counter@6) { m2sled2 := 0 } else { m2sled2 := 1 } if (m2s_counter@7) { m2sled3 := 0 } else { m2sled3 := 1 } # Show most significant bits of slave to master counter: if (s2m_counter@4) { s2mled0 := 0 } else { s2mled0 := 1 } if (s2m_counter@5) { s2mled1 := 0 } else { s2mled1 := 1 } if (s2m_counter@6) { s2mled2 := 0 } else { s2mled2 := 1 } if (s2m_counter@7) { s2mled3 := 0 } else { s2mled3 := 1 } # When switch changes again, the debounce counter starts counting: debounce_counter := 0xff } else { # Show least significant bits of master to slave counter: if (m2s_counter@0) { m2sled0 := 0 } else { m2sled0 := 1 } if (m2s_counter@1) { m2sled1 := 0 } else { m2sled1 := 1 } if (m2s_counter@2) { m2sled2 := 0 } else { m2sled2 := 1 } if (m2s_counter@3) { m2sled3 := 0 } else { m2sled3 := 1 } # Show least significant bits of slave to master counter: if (s2m_counter@0) { s2mled0 := 0 } else { s2mled0 := 1 } if (s2m_counter@1) { s2mled1 := 0 } else { s2mled1 := 1 } if (s2m_counter@2) { s2mled2 := 0 } else { s2mled2 := 1 } if (s2m_counter@3) { s2mled3 := 0 } else { s2mled3 := 1 } # Do debouncing: if (debounce_counter != 0) { # Start counting down: debounce_counter := debounce_counter - 1 if (debounce_counter = 0) { # We reached zero; clear both counters: m2s_counter := 0 s2m_counter := 0 } } } # Copy the slave serial in bit to the interrupt led: intled := slave_serial_in # See whether there is another byte coming by from the slave: if (slave_delay = 0) { if (!slave_serial_in) { s2m_counter := s2m_counter + 1 slave_delay := delay_count } } else { slave_delay := slave_delay - 1 } # See whether there is another byte coming by from the master: if (master_delay = 0) { if (!master_serial_in) { m2s_counter := m2s_counter + 1 master_delay := delay_count } } else { master_delay := master_delay - 1 } }