ucl 1.0 # Copyright (c) 2000-2004 by Wayne C. Gramlich # All rights reserved. library $pic16f630 library clock4mhz library bit_bang package pdip pin 1 = power_supply pin 2 = ra5_out, name = debug_out pin 3 = ra4_out, name = led3 pin 4 = ra3_in, name = serial_in pin 5 = rc5_out, name = led2 pin 6 = rc4_out, name = led1 pin 7 = rc3_out, name = led0 pin 8 = rc2_in, name = in3 pin 9 = rc1_out, name = in2 pin 10 = rc0_out, name = in1 pin 11 = ra2_in, name = in0 pin 12 = ra1_out, name = control_out pin 13 = ra0_out, name = serial_out pin 14 = ground # Shaft state variables: global shaft0 byte global shaft1 byte # Shaft counters: global shaft0_high byte global shaft0_low byte global shaft1_high byte global shaft1_low byte # Shaft low threshold counters: global shaft0_low_high byte global shaft0_low_low byte global shaft1_low_high byte global shaft1_low_low byte # Shaft high threshold counters: global shaft0_high_high byte global shaft0_high_low byte global shaft1_high_high byte global shaft1_high_low byte # Interrupt and shaft direction bits: global interrupt_pending bit global interrupt_enable bit global shaft0_direction bit global shaft1_direction bit global command_previous byte global command_last byte global sent_previous byte global sent_last byte procedure main arguments_none returns_nothing local command byte local glitch byte local id_index byte local high byte local index byte local result byte local temp byte # Initialize everything: shaft0 := 0 shaft0_direction := 0 shaft0_high := 0 shaft0_low := 0 shaft1 := 0 shaft1_high := 0 shaft1_low := 0 shaft1_direction := 0 interrupt_enable := 0 interrupt_pending := 0 glitch := 0 id_index := 0 # Set up pull-ups: command := 0xff # Loop waiting for commands: loop_forever # Get a command byte: command := byte_get() # Dispatch on command: switch command >> 6 case 0 { # Command = 00xx xxxx: switch (command >> 3) & 7 case 0 { # Command = 0000 0xxx: switch command & 7 case 0 # Read Shaft 0 (Command = 0000 0000): call byte_put(shaft0_high) call byte_put(shaft0_low) case 1 # Read Shaft 1 (Command = 0000 0001): call byte_put(shaft1_high) call byte_put(shaft1_low) case 2 # Read Shaft Low 0 (Command = 0000 0010): call byte_put(shaft0_low) case 3 # Read Shaft Low 1 (Command = 0000 0011): call byte_put(shaft1_low) case 4 # Set Shaft 0 (Command = 0000 0100): high := byte_get() shaft0_low := byte_get() shaft0_high := high case 5 # Set Shaft 1 (Command = 0000 0101): high := byte_get() shaft1_low := byte_get() shaft1_high := high case 6 # Set Shaft Low 0 (Command = 0000 0110): shaft0_low := byte_get() case 7 # Set Shaft Low 1 (Command = 0000 0111): shaft1_low := byte_get() case 1 # Command = 0000 1xxx: switch command & 7 case 0 # Increment Shaft 0 (Command = 0000 1000): shaft0_low := shaft0_low + 1 if $z shaft0_high := shaft0_high + 1 case 1 # Increment Shaft 1 (Command = 0000 1001): shaft1_low := shaft1_low + 1 if $z shaft1_high := shaft1_high + 1 case 2 # Decrement Shaft 0 (Command = 0000 1010): if shaft0_low = 0 shaft0_high := shaft0_high - 1 shaft0_low := shaft0_low - 1 case 3 # Decrement Shaft 1 (Command = 0000 1011): if shaft1_low = 0 shaft1_high := shaft1_high - 1 shaft1_low := shaft1_low - 1 case 4 # Clear Shaft 0 (Command = 0000 1100): shaft0_low := 0 shaft0_high := 0 case 5 # Clear Shaft 1 (Command = 0000 1101): shaft1_low := 0 shaft1_high := 0 case 6, 7 # Command = 0000 111x: do_nothing case 2 # Command = 0001 0xxx: switch command & 7 case 0 # Set High Threshold 0 (Command = 0001 0000): high := byte_get() shaft0_high_low := byte_get() shaft0_high_high := high case 1 # Set High Threshold 1 (Command = 0001 0001): high := byte_get() shaft1_high_low := byte_get() shaft1_high_high := high case 2 # Set Low Threshold 0 (Command = 0001 0010): high := byte_get() shaft0_low_low := byte_get() shaft0_low_high := high case 3 # Set Low Threshold 1 (Command = 0001 0011): high := byte_get() shaft1_low_low := byte_get() shaft1_low_high := high case 4 # Read High Threshold 0 (Command = 0001 0100): call byte_put(shaft0_high_high) call byte_put(shaft0_high_low) case 5 # Read High Threshold 1 (Command = 0001 0101): call byte_put(shaft1_high_high) call byte_put(shaft1_high_low) case 6 # Read Low Threshold 0 (Command = 0001 0110): call byte_put(shaft0_low_high) call byte_put(shaft0_low_low) case 7 # Read Low Threshold 1 (Command = 0001 0111): call byte_put(shaft1_low_high) call byte_put(shaft1_low_low) case 3, 4, 5, 6, 7 { # Command = 001x xxxx: do_nothing case 1, 2 # Command = 01xx xxxx or10xx xxxx: do_nothing case 3 { # Command = 11xx xxxx: switch (command >> 3) & 7 case 5 # Command = 1110 1xxx: if (command & 7) = 7 # Return Interrupt Bits (Command = 1110 1111): result := 0 if interrupt_enable result := result | 2 if interrupt_pending result := result | 1 call byte_put(result) case 6 # Shared Interrupt commands. switch (command >> 1) & 3 case 0, 1 # Set Interrupt Bits (Command = 1110 00ep): interrupt_enable := command@1 interrupt_pending := command@0 case 2 # Set Interrupt Pending (Command = 1110 010p): interrupt_pending := command@0 case 3 # Set Interrupt Enable (Command = 1110 011e): interrupt_enable := command@0 case 7 # Shared commands (Command = 1111 1ccc): switch command & 7 case 0 # Clock Decrement (Command = 1111 1000): $osccal := $osccal - $osccal_lsb case 1 # Clock Increment (Command = 1111 1001): $osccal := $osccal + $osccal_lsb case 2 # Clock Read (Command = 1111 1010): call byte_put($osccal) case 3 # Clock Pulse (Command = 1111 1011): call byte_put(0) case 4 # ID Next (Command = 1111 1100): temp := 0 if id_index < id.size temp := id[id_index] id_index := id_index + 1 call byte_put(temp) case 5 # ID Reset (Command = 1111 1101): id_index := 0 case 6 # Glitch Read (Command = 1111 1110): call byte_put(glitch) glitch := 0 case 7 # Glitch (Command = 1111 1111): if glitch != 0xff glitch := glitch + 1 procedure delay arguments_none returns_nothing exact_delay delay_instructions # This procedure will delay for 1/3 of a bit time. local temp byte local alternate bit # Kick the dog: watch_dog_reset # Process shaft 0: temp := $porta & 3 # Convert 2-bit grey code into 2-bit binary: if temp@1 temp := temp ^ 1 switch (shaft0 - temp) & 3 case 0 do_nothing case 1 # Increment: shaft0_direction := 0 shaft0_low := shaft0_low + 1 if $z shaft0_high := shaft0_high + 1 case 2 # Double increment/decrement: if shaft0_direction # Double increment: shaft0_low := shaft0_low - 2 if !$c shaft0_high := shaft0_high - 1 else # Double decrement: shaft0_low := shaft0_low + 2 if $c shaft0_high := shaft0_high + 1 case 3 { # Decrement: shaft0_direction := 1 if shaft0_low = 0 shaft0_high := shaft0_high - 1 shaft0_low := shaft0_low - 1 shaft0 := temp # Process shaft 1: temp := ($porta >> 3) & 3 # Convert 2-bit grey code into 2-bit binary: if temp@1 temp := temp ^ 1 switch (shaft1 - temp) & 3 case 0 do_nothing case 1 # Increment: shaft1_direction := 0 shaft1_low := shaft1_low + 1 if $z shaft1_high := shaft1_high + 1 case 2 # Double increment/decrement: if shaft1_direction # Double increment: shaft1_low := shaft1_low - 2 if !$c shaft1_high := shaft1_high - 1 else # Double decrement: shaft1_low := shaft1_low + 2 if $c shaft1_high := shaft1_high + 1 case 3 # Decrement: shaft1_direction := 1 if shaft1_low = 0 shaft1_high := shaft1_high - 1 shaft1_low := shaft1_low - 1 shaft1 := temp # This code is currently broken: # if alternate # # This code is currently broken! # do_nothing # # Now do range checks: # alternate := 0 # #if shaft0_high < shaft0_low_high || # # (shaft0_high = shaft0_low_high && shaft0_low < shaft0_low_low) # # interrupt_pending := 1 # #if shaft0_high > shaft0_high_high || # # (shaft0_high = shaft0_high_high && shaft0_low > shaft0_high_low) # # interrupt_pending := 1 # #if shaft1_high < shaft1_low_high || # # (shaft1_high = shaft1_low_high && shaft1_low < shaft1_low_low) # # interrupt_pending := 1 # #if shaft1_high > shaft1_high_high || # # (shaft1_high = shaft1_high_high && shaft1_low > shaft1_high_low) # # interrupt_pending := 1 # else # # Copy the bits over: # led0 := in0 # led1 := in1 # led2 := in2 # led3 := in3 # # # Perform any interrupt: # alternate := 1 # if interrupt_pending && interrupt_enable # serial_out := 0 # interrupt_enable := 0 constant zero8 = "\0,0,0,0,0,0,0,0\" constant module_name = "\10\Rotation2B" constant vendor_name = "\15\Gramlich&Benson" string id = "\1,0,16,1,0,0,0,0\" ~ zero8 ~ zero8 ~ module_name ~ vendor_name