' ' LEGO Rotation Sensor test code ' ' Encoder on PA0 and switch/light sensor on PA7 ' ' The lego rotation sensor is queried roughly 122hz ' $regfile = "m16def.dat" $crystal = 8000000 $baud = 19200 ' Config Timer0 = Timer , Prescale = 256 On Timer0 Timer0_isr ' Our timer interrupt hanlder Enable Timer0 Enable Interrupts ' Config Pinb.4 = Output Prog_led Alias Portb.4 ' LED for winkie ' Declare Sub Init_encoder() Declare Function Encoder() As Integer Declare Sub Doencoder() Declare Function Light() As Byte Declare Function Switch() As Byte Call Init_encoder() ' Dim My_encoder As Integer Dim Sys_timer As Byte , Temp As Integer ' ' Do loop prints out only when Encoder changes value ' Do Temp = Encoder() If My_encoder <> Temp Then My_encoder = Temp Print "Encoder=" ; My_encoder ; " Light=" ; Light() End If Idle ' Sleep until next interrupt. Loop End ' Timer0_isr: ' ' State machine to flash LED at 1 hz. Note: the main loop code can use ' the value of Sys_timer to measure out time in 8 ms increments. ' Incr Sys_timer If Sys_timer = 25 Then Prog_led = 0 'enable low output (ON) Elseif Sys_timer = 125 Then Prog_led = 1 'disable output (OFF) Sys_timer = 0 'reset timer End If ' Call Doencoder() ' Return ' Dim Enc_prev As Byte , Enc_val As Integer , Enc_tmp As Byte , Light_tmp As Integer Function Encoder() As Integer Encoder = Enc_val End Function Sub Init_encoder() ' Note: atmel doesn't recommend running the ADC this fast ' but as far as I can tell it works fine. The results will be noiser ' but only by 2-4 counts. Config Adc = Single , Prescaler = 8 Start Adc End Sub ' ' Read and decode the LEGO rotation sensor. (port A0) ' ' The speed at which the encoder can be read is determined ' by the call rate. This sample calls at 122hz ' which should give a top speed of ~300rpm ' Sub Doencoder() Ddra.0 = 0 Porta.0 = 0 Waitus 5 Select Case Getadc(0) Case Is > 850 : Enc_tmp = 2 If Enc_prev = 1 Then Goto Inc_encoder If Enc_prev = 3 Then Goto Dec_encoder Case Is > 700 : Enc_tmp = 1 If Enc_prev = 0 Then Goto Inc_encoder If Enc_prev = 2 Then Goto Dec_encoder Case Is > 450 : Enc_tmp = 3 If Enc_prev = 2 Then Goto Inc_encoder If Enc_prev = 0 Then Goto Dec_encoder Case Else : Enc_tmp = 0 If Enc_prev = 3 Then Goto Inc_encoder If Enc_prev = 1 Then Goto Dec_encoder End Select Goto No_encoder Inc_encoder: Enc_val = Enc_val + 2 Dec_encoder: Enc_val = Enc_val - 1 No_encoder: Porta.0 = 1 Ddra.0 = 1 Enc_prev = Enc_tmp End Sub ' ' Read a LEGO light sensor. (port A7) ' ' The raw output varies from ~600 to ~900, ' depending. I clip the output and shift ' it & invert so low numbers == dark and ' high numbers equal light. If you ' parallel a switch on this port a switch ' closure will read as 0. If only a switch ' is on this port, it will read 255 (open) ' and 0 (closed) ' Function Light() As Byte Ddra.7 = 0 Porta.7 = 0 Waitus 10 Light_tmp = Getadc(7) If Light_tmp < 600 Then Light = 0 Elseif Light_tmp > 855 Then Light = 255 Else Light = 875 - Light_tmp End If Porta.7 = 1 Ddra.7 = 1 End Function ' ' Read LEGO switch (port A7) ' ' functionally redundant with Light(), but ' consumes less power as the outputs are not driven. ' NB - calling this will mess up logic for Light(). Use ' one or the other but not both. ' Function Switch() As Byte Ddra.7 = 0 Waitus 5 Switch = Pina.7 End Function 'end program