' ****************************************************************************

' AnimatedEyesTestCode.txt           ***** FOR TEST USE *****

'

' Make-it-with-Micromite (Part 18)

'

' PE Magazine (July 2020)

'



' This code will check for the correct operation of two 8x8 LED matrix modules

' (i.e. the MBR's eyes), as well as checking that the IR receiver works.



' RUN the code to ensure you can see an animation displayed on both 'eyes'.



' DO NOT PANIC IF YOU DO NOT FOLLOW THE ANIMATION CODE!!

' (it is rather complex to follow the logic without a detailed explaination.)



' At any time while the eyes are animating, press a button on an IR

' remote transmitter ensuring that you see a response on your terminal screen!

'

' NOTE: Remove JP8 jumper to keep the MRB powered up while in the EDITor

'



' ****************************************************************************



' ----------------------------------------------------------------------------



' SET-UP

' ======



OPTION AUTORUN ON              ' set program to automically RUN on power-up



IR DevCode,KeyCode,myIR_Int    ' enable IR detection - see SUB myIR_Int which

                               ' is located at the very end of this code!





SPI OPEN 300000,3,32           ' configure SPI port for communication to 8x8's

DIM eye(7)                 ' an array that holds the 8x7 solid-eyeball pattern

CS=21               ' define I/O pin connected to the LED MATRIX module CS-pin

PIN(CS)=1                  ' default to high (any SPI data is ignored for now)

SETPIN(CS),dout            ' set up the I/O pin as defined in above 2 lines



DIM LeyeTemp(8) As INTEGER ' array used during calculation of LEFT eye data

DIM ReyeTemp(8) As INTEGER ' likewise for RIGHT eye



LED_Init                   ' SUB to initially set up both LED matrix modules



eye(1)=&b00111100          ' define 8x7 (rugby ball shape) LED eyeball pattern

eye(2)=&b01111110            ' This is used as a 'background' and loaded into..

eye(3)=&b11111111            ' L(R)eyeTemp array each time the eyes are drawn.

eye(4)=&b11111111            ' The pupil is then drawn at the correct position

eye(5)=&b11111111            ' and finally the eye drawn either in Up or Down

eye(6)=&b01111110            ' position (ie on first row (Up), or second

eye(7)=&b00111100            ' row (Down)) - see DrawEye SUB below!



' LEyePos = Left-EYE position. 0=Up (top=1st row), non-zero=Down (top=2nd row)

' REyePos = as above but for Right-EYE



' Ly (1 to 7) = which row (from top of 8x7 eye) where the Left-PUPIL is drawn

' Ry (1 to 7) = as above but for Right-PUPIL (pupil=2x2 block with LEDs OFF)



' Lx (0 to 9) = column position for the Left-PUPIL (9=no pupil)

' Rx (0 to 9) = as above but for Right-PUPIL (0 or 8 = half a pupil!)



pupil=&b1100000000         ' holds the pupil row pattern - used in DrawEye sub

                           ' NOTE: pupil is 2x2 block (LEDs OFF) see PE photos!

                           ' Default value=pupil off to the left of the eyeball

                             ' hence why 10 digit binary value

RANDOMIZE TIMER            ' ensures different animation effects each time



d=50                       ' variable used to hold 'delay' between animations

                             ' hence speed of animation. Decrease to speed up.





' ----------------------------------------------------------------------------



' MAIN PROGRAM

' ============



DO                                         ' DO..LOOP to continually animate

  LEyePos=Int(Rnd()*2)                     ' Random Left eye position (0 or 1)

  REyePos=Int(Rnd()*2)                     ' Random Right eye position

  Ly=Int(Rnd()*2)+3                        ' Random Left PUPIL row

  Ry=Ly                                    ' ensure right PUPIL is same height

  Lx=3:Rx=3:DrawEye:Pause d                ' define PUPILs column and draw eye

  Lx=2:Rx=2:DrawEye:Pause d*5*(Int(Rnd()*5)+1) ' define new PUPILs column...

  Lx=3:Rx=3:DrawEye:Pause d                    ' and another ....

  Lx=4:Rx=4:DrawEye:Pause d*5*Int(Rnd()*5)     ' continuing to make it animate

  Lx=5:Rx=5:DrawEye:Pause d                    ' changing Lx and Rx moves pupil

  Lx=6:Rx=6:DrawEye:Pause d*5*(Int(Rnd()*5)+1)   ' sideways

  Lx=5:Rx=5:DrawEye:Pause d

  Lx=4:Rx=4:DrawEye:Pause d*10*Int(Rnd()*5)

LOOP                                        ' repeat over with new 'positions'





' -----------------------------------------------------------------------------



' SUBROUTINES

' ===========





SUB DrawEye                        ' DO NOT PANIC IF YOU DON'T FOLLOW THIS SUB!



  'draw both pupils in correct place

  FOR i=1 TO 7

    IF ((Ry+0)=i) OR ((Ry+1)=i) THEN

      rtemp=255-(pupil>>(Rx+1))

      ReyeTemp(i)=eye(i) AND rtemp

    ELSE

      ReyeTemp(i)=eye(i)

    END IF



    IF ((Ly+0)=i) OR ((Ly+1)=i) THEN

      ltemp=255-(pupil>>(Lx+1))

      LeyeTemp(i)=eye(i) AND ltemp

    ELSE

      LeyeTemp(i)=eye(i)

    END IF

  NEXT i



  'draw eyes Up or Down

    IF REyePos=0 THEN

      ReyeTemp(8)=&H00

    ELSE

      FOR i=8 TO 2 STEP -1

        ReyeTemp(i)=ReyeTemp(i-1)

      NEXT i

      ReyeTemp(1)=&H00

    END IF



    IF LEyePos=0 THEN

      LeyeTemp(8)=&H00

    ELSE

      FOR i=8 TO 2 STEP -1

        LeyeTemp(i)=LeyeTemp(i-1)

      NEXT i

      LeyeTemp(1)=&H00

    END IF



    ' DRAW EYE

    FOR i = 1 TO 8

      aa=SPI( (((i*256)+ReyeTemp(i))*(2^16)) Or ((i*256) Or LeyeTemp(i)))

      PULSE cs,1

    NEXT i

END SUB



' -----------------------------------------------------------------------------



SUB LED_Init                      ' initialise the MAX7219 display modules

  AA=SPI(&H0C000C00):PULSE cs,1

  AA=SPI(&H09000900):PULSE cs,0.1

  AA=SPI(&H0A050A05):PULSE cs,0.1

  AA=SPI(&H0B070B07):PULSE cs,0.1

  AA=SPI(&H0F000F00):PULSE cs,0.1

  AA=SPI(&H0C010C01):PULSE cs,0.1

END SUB



'------------------------------------------------------------------------------



SUB myIR_Int

  PRINT "IR detected: Device Code="+STR$(DevCode) + ", Key Code="+STR$(KeyCode)

END SUB