Korchoi's (Extremely limited) POV clock

Discussion in 'Homework Help' started by korchoi, Jun 5, 2015.

  1. korchoi

    Thread Starter Member

    Jun 5, 2015
    Hi there, this is korchoi and in my first thread i will be building a POV clock with simple specs. Here is the main challenge of the project:
    Build a POV clock with a very limited selection of components. Merely displaying the time in the pseudoscreen is enough.
    bonus points if it can display animations.

    Now i will explain why it is a "very limited POV clock":
    1:My country(Brazil) is electrophobic, and this is amplified for the city where i live(which used to be merely a big sugar cane farm zone).
    Thus, The selection of electronic components around the area is limited to the most popular parts of 30 years ago.
    no, seriously, the electronics stores around here only sell pic16f628 micros. No LDR's, No ARM micros, No pin headers, no CPLD's or FPGA's. very basic stuff here.
    expect ancient 74xx-based glue logic, JDM programmers, cheap plastic pcb's and ghetto-style mechanical structures.
    This is a Team effort of Me, Me, Me, Me and 2 other colleagues who don't know much about electronics.They can't solder, program, or plan electronic circuits.
    My 2 teammates are useless(just like the rest of the classroom).
    3: I am still new to electronics, so if throw <snip> in the fan, the entire thing will be quick to fix for its simplicity.

    Enough rambling, here is the schematic:
    schematic coming soon!
    Last edited by a moderator: Jun 7, 2015
  2. korchoi

    Thread Starter Member

    Jun 5, 2015
    I am currently working on the first prototype that will simulate the rotation of the board. here is the led grid, which according to the programming will display the letter "A", then "B", then "C". Time of transition from one image to the other is 0.5s.
    -1x PIC16f628
    -1x LED GRID


    The hardware of the fixed(not-spinning-on-a-cpu-fan) prototype is not ready yet.I have only been simulating up to now.Also, fitting 40 LED's, 13 resistors and 5 transistors is quite cumbersome in a breadboard.

    PortA will multiplex the Columns , each of the 8 rows in a column being controlled by portB in series with a resistor. All that happens in steps of (3333 x 4) clock cycles, which at 4MHz from the internal oscillator leads to 3333us each step, outputting (5x60) lines per second, or 60 frames per second. Why 60fps? because i can! and i also plan on making some smooth animations that impress those who see.Just because its limited doesn't mean it's boring.

    On each CCP match trigger, a bit in a register file will set. This bit is later tested in the main loop, which then calls the output routine.

    The output routine clears the previously set bit and Increments the FSR and line number. FSR contains the address that the index register points to. In this case, the image area(starts at address 0x40).If line number overflows, then subtract FSR by five(index points five lines behind), Next frame. on frame overflow, next image. on image overflow, restart.


    Attached to this post is the source code. I have found a buzzy problem:
    While simulating in MPLAB, The PortB values(LED Matrix output) are wrong!
    Please someone fire up MPLAB and verify it only happens to me and if not, what should i do? i am clueless on this. Something on the output routine, maybe?
    Also, don't mind the config word commented out, that's because i forgot do disable the watchdog. Set config manually to watchdog off, internal clock and everything else to digital IO.

    -actual clock portion of the prototype
    -Text mode(display ASCII characters stored on memory)
    -PC Script to turn colored images into MonoChrome char string( 8 monochrome pixels per char )
    -frame count on a per-character basis( eg. repeat A 30 times, repeat B 10 times)
  3. JohnInTX


    Jun 26, 2012
    Well pard'ner. What you have is what we down here call a danged good question - meaning I don't know what's going on either.
    I ran up your code in MPSIM (both X and 8.63) and indeed RB3 does not follow what you fetch out of the RAM array. I saw FSR correctly load WREG from 40h to 44h on successive passes but RB3 seemed stuck low or high for a long period. I reviewed the other stuff that uses RB3 and your setup looks OK to me. There are some discrepancies in the databook between the table indicating RB3's alternate functions and the block diagram but it looks like you've turned all that stuff off.

    Messing around I:
    Relocated the array in RAM
    Disabled interrupts for the indirect fetch to W and write to PORTB
    Disabled LVP in the config regs (although that uses RB4) - grasping at straws here.
    Changed TMR1's mode to compare without the reset (that's been problematic on some parts).
    Reviewed the config of other peripheral registers in the SFR watch window - they look OK.

    So.. I don't know what's happening. It sure looks like a config problem or one where a peripheral is still using the port bit - particularly since the erroneous RB3 seemed to toggle from stuck 0 to stuck 1 over time.

    I have to get busy but here are some observations:
    You don't have any context save/restore in the interrupt routine - you can't do that. Even if you aren't changing W, STATUS etc, what happens if you get interrupted right after setting RB0 to access bank 1 for something.. Now, you can't see your PIR flags and *boom*. The databook sec 14 shows a basic context restore/save. Its possible that you are confusing MPSIM here - grasping at straws again... But again, you MUST ALWAYS do a proper context switch. Once you have saved the context, be sure to explicitly set RPx, IRP, and PCLATH before any jumps if you have more than one ROM bank.

    Your well documented source is great. Most posters don't do that. Here are some things that jumped out since it was so well documented.
    Don't enable GIE until ALL of your timers, IEs etc. are fully configured and ready to go. Clear any pending interrupt flags just before setting GIE.
    Don't use #define to specify RAM addresses - use EQU or CBLOCK (preferred) instead. #define gets evaluated with a simple text substution - its assembles with the value but that value does not get associated with the name in the symbol table so you can't do symbolic debugging. If you use EQU or CBLOCK, you can open a watch window and type in the symbol name which will follow any source changes. Using CBLOCK will help avoid using the same RAM for two different things by mistake.
    The first PORTB image you fetch is from 41h, not 40h - be sure your row/col sync is OK with this. I like to do the bump/wrap FSR right AFTER I use it to avoid this kind of thing.
    You don't need (or want) the multiple ORGs. That leads to inadvertent code overlays. Do something like this:
    Code (Text):
    1.  ORG 0 ; RESET vector
    2. nop ; some emulators like this
    3. goto startup
    5. ORG 0004 ; locate the interrupt
    6. Interrupt:
    7. save context
    8. do things, clear their InterruptFlags..
    9. restore context
    10. retfie
    12. startup:
    13. immediately after the end of the IRQ, MPASM will  figure it out for you.
    At this point, my next steps would be to
    1) fix the interrupt code - that needs to happen in any case
    2) relocate the interval time to TMR2/PR2 to avoid any TMR1 conflict with RB3 - even though there shouldn't be that I can see. DISABLE the CCP / TMR1 module.
    3) Get the config flags set in the source - don't rely on defaults (actually here or anywhere).
    4)Revisit every register in the SFR list and explicitly set it to not interfere with PORTB or other things. It looks like you got everything but MPSIM is still unhappy. May we missed something or there is a hole in the databook..

    If none of this fixes RB3, I'd zip the code and send on a support ticket to Microchip. Since it is so well documented and assembles first time, they should be able to find out what's going on. If you go that route be sure to post what they say. Maybe a stupid mistake that neither of us can find but better to be called stupid than to stay stupid, I always say.

    Good luck.
    Post a quote or 'like' so I'll get alerted when you reply.
    Last edited: Jun 6, 2015
    korchoi likes this.
  4. WBahn


    Mar 31, 2012
    MOD NOTE: This appears to be some form of academic assignment, so it will be moved to the Homework Help section.
  5. korchoi

    Thread Starter Member

    Jun 5, 2015
    LOG 1
    (<snip>, i explicitely disabled the Watchdog Timer in The config register, yet it keeps timing out!) config register fixed.
    after changing the isr and initial setup portion to use timer2 as the timing source, things get messier.)
    nevermind, fixed it.Forgot to clear the bits once they are set by the isr.

    (Now FSR will be changing in an unknown pattern to me. Instead of incrementing 5 times then returning, it just jumps randomly.
    Setting a breakpoint for each time output is called gives me the normal "0x40 -> 0x41 -> 0x42" sequence.
    I must have forgotten to disable an interrupt or 2.)
    You did it. Switching to timer2 actually fixed the stuck pins on PortB!
    Now it shows A and B nicely and according to plan.Now you wonder, did i test letter C?No, because:
    i need a better way of debugging this code. pressing f9 30+ times turned out to be annoying.
    Now, i need to investigate what made the portB pins get stuck. Surely(as proved by the test) not a design limitation such as pull-ups or ST inputs.
    If you don't mind, check out the new source code and point any potential butter slips in my code.
    I will do as you say and Send a report to Microchip.I want to know what part of timer1 or CCP got the pins stuck.
    Missing the first line of 'A' won't be a problem, because it only happens once at the very start up, on the first frame.
    but i might still change that.Near the end.For good code practices.
    Attached down here is the source code.
    If someone here is up to the challenge...
    you.Yes, you there, reading my post. I dare you to run this on a simulator (ISIS or whatever) with the 5x8 matrix from the previous post.
    If you do, record it and link to youtube.
    oops, forgot source code.
    there you go.
    Last edited: Jun 7, 2015
  6. JohnInTX


    Jun 26, 2012
    Good job! You have a grip on this that I like. That's not a solution because we don't know why it happened but it narrows the search.
    Yep, we DO have to understand why that is. As I said, I don't know either but moving to TMR2 is good info.'

    Tired and late. Will look at other stuff tomorrow.. Your post shows you are thinking along the right lines. See you tomorrow..
  7. MrCarlos

    Active Member

    Jan 2, 2010
    Hello korchoi

    I have developed schemes according to what you have published in your messages.
    I used the PIC16F628A and LED matrix that looks at post #2 and code(ASM) that you enclose in the same message.
    The ISIS Proteus simulator has only dot matrix: 5x7 and 8x8.

    First of all let's see how is the 8x8 Dot-Matrix in ISIS Proteus simulator, in this video:
    https://www.youtube.com/watch?v=jaSrDJaGSgk ISIS Proteus 8x8 Dot-Matrix.
    You got it ??

    Now, to the simulator it is difficult to handle an array with LED’s; Note that slow changes from column to column in this video:
    https://www.youtube.com/watch?v=rplaH73duH0 Your POV Clock 1 With LED's.
    I compiled the code that you enclose in your message #2 and assign it to the design developed with LED’s
    Look at the frequency of the PIC.

    Now watch this video with the new code that you enclose in your post #5 and with the 8x8 Dot-Matrix's Proteus ISIS Simulator:
    Your POV Clock 2 https://www.youtube.com/watch?v=UwhQqdoMFHs With Proteus ISIS 8x8 Dot-Matrix.

    We can distinguish the letters A, B and C.
    The letter A is best distinguished.
    Letter B with some imagination one can see.
    The letter C is almost looks good.

    Good luck with your design
    korchoi likes this.
  8. korchoi

    Thread Starter Member

    Jun 5, 2015
    sorry, but i can't see the videos you linked. Here says it's a private video.
    This is so fascinating, 2 days on the forum and i already got help from the other side of the world.The prealpha firmware is ready and a simulated prototype can be shown to a teacher eager for results! talk about using the internet the right way.
    I have been dwelling in forums for 6 years. It's about time i joined the party.Thank you, John, for the support. Thank you, Carlos, for the video.I don't have money or or permission for proteus, so seeing the matrix output letters(of course, when you make it available) will be glorious.
    coming up next:
    -indexed and decoded ASCII Table in Memory

    A large(5 lines * (95 + 128 Latin extended characters) ) = 1.115KB memory section containing bitmaps for all characters.
    Each individual ASCII character in a defined input string will be interpreted into its equivalent index location for the Matrix output.
    I will have to store this in serial flash(remember, electronics here are scarce), unfortunately making the feature less likely to be implemented anytime soon.
    -scrolling text

    DIODES AS PHOTOSENSORS for rotational sync
    So i went to the local electronics store. "Do you sell LDR's? photodiodes? phototransistors?" "No.We don't sell any of these.But we sell LED's."
    I remember that HackADay article saying that LED's can react to light, too.Just less than their specialized siblings.
    I am considering using Two LED's for synchronization. One sits alight on the base, the other senses on the rotating part.The sense diode is attached to an internal comparator hacked up into a non-inverting amplifier. The amplified small peaks are fed into another comparator set as schmitt trigger.The resulting pulses are used as interrupts. Each pulse will refresh the screen.But it doesn't stop there. The time elapsed to get a certain amount of pulses will be divided by the number of virtual pixels the screen is supposed to have.the inverse of (Time for n pulses / number of pixels) will be the display's "pixel clock".
    Now a concern with the timing is that there is no hardware divider in PIC 8-bit. A software inplementation will take away precious cpu cycles.
    Maybe a rudimentary PLL to multiply the LED pulse's frequency is a better idea...

    I also have a pic16f877 borrowed from my school. I plan to port the project to this bigger part near the end of development. Whith it, i can have more program space, more RAM and even SPI or I2C for interfacing to external memory. Now imagine a board with 16 LED's spinning in a dark room... just fabulous.
  9. MrCarlos

    Active Member

    Jan 2, 2010

    Well, it was very difficult to upload the videos and make them public(shared with everyone).

    I could never make them public so that any one could see and/or download.

    I uploaded to a server, those videos, and here are the links:
    Dot-Matrix.wmv 8x8 http://wikisend.com/download/408058/ISIS
    (Dot-Matrix.wmv 8x8 ISIS)

    http://wikisend.com/download/311082/Your POV Clock (1) .wmv
    (Your POVClock (1).wmv)

    http://wikisend.com/download/283488/Your POV Clock (2) .wmv
    (Your POVClock (2).wmv)

    But now you'll have to download them to your PC and open them with Windows Media Player.

    Good luck with your project.
    Last edited: Jun 8, 2015
  10. korchoi

    Thread Starter Member

    Jun 5, 2015
    I don't know what you did, but the youtube link works now.
    oh god
    it works
    i can see A, B and C


    Side note: do you think anyone in the world will google "extremely limited pov clock" and find ths article first time?
  11. MrCarlos

    Active Member

    Jan 2, 2010
    Hello korchoi

    Ok just what I did is enter to my YouTube account and push the PUBIC button.

    Yes, of course anyone that navigate across the WEB can find this article.
  12. JohnInTX


    Jun 26, 2012
    Looks like good progress and I see you have taken my advice on the interrupts. Well done.
    But you have a couple of problems in the interrupt service routine in your context save / restore. In particular, you use instructions that change flags. For example, just before retfie, you restore W using movf, that will affect the Z flag in the status register. If its not the same as when the interrupt happened you will have unexpected problems in the main program. Interrupt bugs such as this are extremely difficult to debug.

    Moving to a multi-bank PIC like the '877 adds some other things to worry about.
    1) You have to save W but you don't know what bank you are in and you can't change banks without fouling up the STATUS context. The solution is to save W in the common RAM area (usually 70h-7fh) -OR- reserve one byte in each RAM bank for W. Declare IRQsaveW at 20h for example and reserve 120h, 220h and 320h (for a 4 bank PIC) for use. I like the latter method because not all multibank parts have common RAM. When they DO, that RAM becomes VERY valuable for parameter passing, common flags etc. that are used heavily.
    2)You have to save PCLATH if you have more than one ROM bank - its part of the current context of the program.

    The code shows an interrupt handler from a real project. It supports TMR0 and the USART. Of note:
    1) The interrupt enables are inspected before the interrupt flag - necessary if you ever disable an interrupt, here when there are no characters in the transmit buffer. If you never disable the interrupts, you can omit these tests.
    2)The service routines are large (actually in other files). They are JUMPED into rather that CALLED to save stack. An interrupt service routines is always entered from and returns to a known place so you don't need to call them. While on the subject, I allocate a midrange stack to allow 5 levels for the main routine and 2 levels for the interrupt service (one of which is used by the interrupt itself). That leaves a one level cushion.
    3)The return point for all of the service routines is at the TOP of the tests to see if any other interrupt flag has raised while servicing the original interrupt. There's no sense in restoring context and returning if you are only going to get another interrupt. Might as well save the time.
    4)At the end of the list of testing interrupt flags it says 'who dunnit?' If you ever get to that line of code, you have a serious problem i.e. something unexpected has caused an interrupt that will never be serviced, hanging the processor. I deleted the error handler from the original code - how its handled is up to you.
    5)At 0004h you GOTO the interrupt routine - a bad thing to do. You can't do ANY jumping/calling until you are sure that PCLATH is pointing to the correct ROM page and you can't do that before you have saved context (and the current PCLATH). So.. its usually best just to do all the interrupt stuff in place - put it into an include file like I did if its cluttering up your main file. At the very least, you have to save context down to PCLATH before jumping - I don't like that myself..
    6)The if $ != 0004h statement. This code was in a separate file that was included during the assembly. This statement directs the assembler to make sure it didn't get included in the wrong place. The ERROR statement will be printed in the output window if there is a problem.

    Some of your new weird problems may be to incorrect IRQ context save..

    Actually, now that you have read all of that, I should add that with the current code (or at least the last one I looked at) you don't really need interrupts. You are correctly setting a flag to indicate that the timer event happened but wind up just polling that interrupt-driven flag. All things being equal, you could dispense with interrupts altogether just poll the timer/CCP flag. I wouldn't recommend that at all since you'll eventually need interrupts somewhere, but its worth noting.

    Code (Text):
    2. ;*****************************  IRQ.INC   *********************************
    4.           ; This contains the interrupt handler.  It MUST be at location 0004h
    5.           ; Has save and restore context  routines.
    6.           ; After the point indicated, we can jump to an extended handler.
    8.           ; All interrupt service routines must GOTO IRQreturn when done.
    10.           ;*********************  IRQ SERVICE  ****************************
    12.           ; Saves W in whichever rambank is active
    13.           ; Save STATUS, PCLATH and FSR in bank 0
    14.           ; Polls sources and goes to routines in ROM bank 0
    15.           ; IRQ routines return by goto here for context restore
    17. serviceIRQ:
    19.           if $ != 0004h
    20.             ERROR "serviceIRQ not located at 0004h!!"
    21.           endif
    23.           movwf   IRQsaveW        ; save W, may wind up in any RAM bank
    25.           swapf   STATUS,W        ; get status reg WITHOUT CHANGING flags
    27.           banksel 0               ; all other context is saved in bank 0
    28.           movwf   IRQsaveS      ; save swapped STATUS
    30.           movf    PCLATH,W        ; save interrupted routine's upper address
    31.           movwf   IRQ_PCLATH      ; this is NECESSARY for multi bank ROM
    32.           clrf    PCLATH          ; run irq service in rom 0
    33.                                   ; after this point can jump to more service
    34.                                   ; routine
    36.           movf    FSR,W           ; save FSR its used in the service routines
    37.           movwf   IRQsaveFSR
    39.     ;---------------- IRQ RETURN ----------------------
    40.     ; Service routines jump here when done. Re-polls
    41.     ; interrupt flags before exit to see iff anything needs
    42.     ; to be done before exiting.
    44. IRQreturn:
    45.           banksel    0
    46.           bcf     IRP
    48.           movlw   PIE1            ; we'll be looking at this a lot
    49.           movwf   FSR
    51.           btfss   INDF,RCIE         ; SIO RX enabled?
    52.           goto    noRX            ; nope
    54.           btfsc   PIR1,RCIF       ; SIO RX char?
    55.           goto    svcRXIRQ        ; get it! run RX state machine, ram bank 0
    57. noRX:
    58.           btfss   INDF,TXIE         ; SIO TX enabled? (means have chars to send)
    59.           goto    noTX
    60.           btfsc   PIR1,TXIF       ; xmit empty?
    61.           goto    svcTXIRQ        ; yup, send it
    63. noTX:
    64.           btfss   INTCON,T0IE     ; timer 0 enabled?
    65.           goto    noT0            ; nope
    66.           btfsc   INTCON,T0IF      ; else, check and service it
    67.           goto    svcTMR0
    70.           ;else.. who dunnit???  If the code gets here its an ERROR - an
    71.       ; unexpected (and not coded) interrupt has occurred
    73. noT0:
    74.           banksel 0               ; make sure we are in bank0
    76.           movf    IRQ_PCLATH,W    ; restore upper address
    77.           movwf   PCLATH          ; no branching after this..
    79.           movf    IRQsaveFSR,W    ; restore FSR
    80.           movwf   FSR
    82.           swapf   IRQsaveS,W      ; get saved status WITHOUT changing flags
    83.           movwf   STATUS          ; now.. we are in the original RAM bank
    84.           swapf   IRQsaveW,F   ; get saved W without changing flags
    85.           swapf   IRQsaveW,W
    87.           retfie
    88.           SUBTITLE ""
    89.           PAGE
    As far as your data tables go, I would recommend a PIC big enough to hold them - much simpler than adding an I2C or SPI part. The '628 has 2K of ROM a little more than half would be used up by the data table. How tight can you code the rest? At any rate, the kind of things shown for the interrupt routine would work for any midrange PIC so have at it. You also might consider the 18F or enhanced midrange if you can get one. EhMid is particularly good at table lookups since you can use the FSRs to directly address data in ROM.

    But for the midrange PICs you mentioned, if you put the data tables in the PIC ROM, you'll need to use a full 16bit table lookup scheme. You still have to jump into the table of retlw xx but you can't just ADDWF PCL,F - that's only good for 256 entries. The solution is to calculate the 16 bit address of the entry then CALL the lookup routine which moves the high byte of that calculated address to PCLATH and moves (not adds) the low byte to PCL. Not hard.

    Haven't looked at the other stuff but sounds like you have some good help here. Clean up that interrupt stuff and carry on.
    Last edited: Jun 8, 2015
  13. korchoi

    Thread Starter Member

    Jun 5, 2015
    at the start i did not know what you were talking about when reffering to jump by changing pclath or when mentioning bank awareness.
    After a nauseous trip on your text, i realize you were actually reffering to Banking in the instruction memory. Now that's some overhead from china.
    this architecture is really showing its age. When i get some money i will try to ship one of those awesome arm micros with bootloader.
    But that is still way ahead(like, 7 months ahead). For now, just a floating screen showing scrolled time will do.
  14. JohnInTX


    Jun 26, 2012
    Nauseous trip? You wound me :rolleyes:
    Nevertheless, that's what you have to do if you do it on midrange PIC.
    Good luck.
  15. korchoi

    Thread Starter Member

    Jun 5, 2015
    [LOG 2]
    I ran to the hardware store near my school and bought over 50 LED's, 20 1k2 resistors, 10 transistors and 2 small veroboards(the last 2 of the stock)
    The end bill sucked me over 30 Royals, which crudely translates to a bit over 10 bucks.
    The matrix ended up looking nicer than i expected.Cute little thing.
    Now all that is left is to solder the parts together right in front of my teammates with good'ol CAT4 solid core wiring.
    The wiring shall be connected to a breadboard with the PIC.
    Ideas for programming:
    Scrolling text on horizontal will be as simple as setting the output routine to show 5 lines of the draw area, offseting the start point every few frames.
    Scrolling text on vertical just takes some smart bit rotating without the carry bit every few lines.Of course, this just loops the image vertically. To scroll into additional data, the upper bits of the following image would replace the lower bits of the first. So, to scroll from letter 'A' to letter 'B', there are 4 steps:
    Step 1:Rotate bytes from A and bytes from B as Pairs.This means rotate Pairs A1B1, A2B2, and so on up to A5B5.
    Step 2: Repeat until rotated 8 times(A and B swapped)

    Now that would mess with the positions of each image.Considering this, i can separate the draw area into Scratch zone(display) and Sprite zone(store).
    The Original images would be copied from the sprite zone into the scratch zone, where my program can modify it however the programmer desires.
    Because a copy would be stored in the sprite zone, The image A can still be fetched in its original form.Just copy it again from the sprite zone.
    Of course, it would take up more RAM, but it would just be merely as large as the matrix.
    I don't really need full ASCII for this thing. (27*5=135) Bytes of sprite zone will occupy RAM on minimal ASCII mode(just a to z with comma)
    A completely isolated minimal clock mode(just 0 to 9 + that double dot) occupies (11*5=55) Bytes of sprite zone.
    I can also store It all in Macros of calls.
    Instead of just defining all sprites into RAM, Store each one as A "declaration call"
    Each macro follows this template:Store 5 previously #define'd constants into Scratch zone.This way, no ram cache fills up the PIC.
    Of course, it would gobble up more cycles(at least twice the access time because W is the obligatory Bridge between EVERYTHING.)
    At least the instruction cycle number is consistent across most instructions, unlike AVR.
    Hooray for optimization!
  16. korchoi

    Thread Starter Member

    Jun 5, 2015
    Update(probably the last for this thread...):
    The LED matrix is finished and i tested it led by led...
    it works... kinda.
    Lighting pixel by pixel up, i found that while most would just light up as expected some would give funky results...
    Some coordinates led to the actuation of completely isolated LED's that have nothing to do with the combination!
    For example, let's say led 5 of row 1 is funky. if i activate collumn 1 and set to light LED 5, led 1 of collumn 3 lights up and led 7 of column 2 would light up.
    Kind of WTF'd me, 'cause if i didn't activate collumn 2, then that LED shouldn't possibly light up in that situation!
    Shouldn't have tried point to point soldering on perfboard without wire wrapping or using sockets.I've made a terrible mistake...
    That level of complexity is already Enough. I'll just do an open loop "bob-blick" style clock, without even sensing the rotation... Very ghetto-style method for the projects. That's what came to mind when i snapped because this world hole of a city doesn't have anything! Shipping for parts here is a nightmare, cause the few good stuff you can find online is expensive. Don't get me started with overseas shipping: Slow to deliver(3 months or so from china) and fast to tax(and oh, boy, how they are good at this... 200% tax over product and shipping combined!).
    Sorry if this contains too much useless information. I'll cool my head.Could be sleep depravation making me edgy.
    What did we learn from this?
    Avoid high complexity when there is scarcity of parts.