#avr Logs

Jul 31 2020

#avr Calendar

04:27 AM landau: Hello. I have a ATMEGA8535 with a TIMER1 interrupt. In the IRS I call a function, called every 5ms. This function checks a 8x8 keypad matrix. In the function I have two for loops, the first one: "for (i=0; i<=7; i++)" and the second one within the first one "for (j=0; j<=7; j++). If a button is pressed I send a UART message to the computer. Now I
04:34 AM landau: found that the routine works only if I set the first for only on one iteration, such as "for(i=0; i<=0; i++)". Do you know why?
04:45 AM cehteh_: landau: possibly your isr takes to long and blocks the uart?
04:45 AM landau: I tried to disable the UART but it does not work
04:46 AM cehteh_: then some other bug
04:46 AM cehteh_: check your code
04:46 AM cehteh_: anyway you prolly dont want to do the keyboard scanning in a ISR, cant you just schedule it from isr but run it as normal program?
04:47 AM cehteh_: or, if isr, then use the isr to step through the loop rather than doing all
04:47 AM cehteh_: that also allows for the levels to settle
04:48 AM cehteh_: isr() { read_current(); increment_scanline(); } .... kindof
04:49 AM landau: ok
04:49 AM cehteh_: doing so may already fix your other bug :D
04:53 AM cehteh_: .. and dont use delay() :D
04:53 AM landau: yes exactly
05:02 AM Thrashbarg: hmm
05:24 AM cehteh_ is now known as cehteh
09:35 AM PublicWiFi is now known as MaccasWiFi
09:38 AM MaccasWiFi is now known as PublicWiFi
10:05 AM PublicWiFi is now known as MaccasWiFi
10:09 AM MaccasWiFi is now known as PublicWiFi
11:25 AM landau: Hello, I need to control a 4051, so I need to set 3 bits on PORTD of my ATMEGA8535. The 4051 is connected like this: A--->PD5, B-->PD4, C-->PD3, Any idea on how to generate a 3bit sequence, 000, 100, 010, and so on? Thank you
12:20 PM cehteh: what kind of bit sequence is that?
12:21 PM landau: PORTD |= (i & 0x01) << 5 | ((i >> 1) & 0x01) << 4 | ((i >> 2) & 0x01) << 3;
12:21 PM cehteh: i mean you can either store it in a table or generate it arithmetically .. whatever works for you
12:21 PM landau: but now I used an array to store it and it works
12:21 PM cehteh: how many entries?
12:22 PM landau: 8
12:22 PM landau: I need to control a 8x8 keypad
12:23 PM cehteh: whats a 4051? shift register?
12:23 PM cehteh: ah mux
12:23 PM landau: analog mux
12:23 PM LeoNerd: Oh /that/ 4051
12:24 PM LeoNerd: also yeah your "and so on" is a bit vague
12:24 PM LeoNerd: If you're just wanting a 3-element sequence doing one bit at a time, consider shifting it
12:25 PM LeoNerd: bit >>= 1; if(!bit) bit = 0b100;
12:25 PM cehteh: demux for reading mkay
12:25 PM cehteh: but for scanning you could just use a shift register
12:25 PM cehteh: whatever works :D
12:25 PM landau: the board has a 4051
12:26 PM cehteh: iirc there are IC's doing keyboard matrix reading completely
12:26 PM cehteh: dont you need 2 of them?
12:26 PM cehteh: anyway ... should work
12:26 PM landau: I have one, the other 8 are directly connected to PORTC
12:27 PM cehteh: ah
12:27 PM landau: wait I will share the routine...
12:28 PM cehteh: you drive the scan with the 4051 and read on portc?
12:28 PM landau: yes exactly..
12:30 PM cehteh: cant you just increment the mux? 0..7
12:30 PM landau: https://www.paste.org/108275
12:30 PM landau: here is the code...what do you think?
12:30 PM cehteh: actually you just increment w/o any check but mask it when you set the port
12:31 PM landau: I use two for cycle but I can use one I guess using i=0 to 64 and use i/8 and i%8
12:32 PM cehteh: way too complicated
12:32 PM landau: what only one cycle?
12:34 PM cehteh: just i+=64; and set PD = (PD & ~0x380) | (i<<3 & 0x380)
12:35 PM cehteh: with some celverness you may even find a way to use the PIN toggle mask then you can do it all in once instr .. but i guess that hardly matters here
12:37 PM landau: ok wait...I have to understand what you wrote :P
12:38 PM cehteh: and remember what i saied earlier? instead looping for scanning you just do one read per timer interrupt and increment to the next scanline
12:38 PM cehteh: no for
12:39 PM cehteh: then you can interrupt more often when you need faster reads but your interrupt routine will be much much shorter
12:39 PM cehteh: only a few lines of code actually
12:40 PM cehteh: err .. hex error 0x38 w/o 0 or 0b111000 is the mask you want or?
12:40 PM landau: actually this is a very good idea..the code is called every 5ms by timer1 interrupt!
12:41 PM cehteh: yes make that 1ms and have a 10 times simpler ISR ... that'll most likely pay off
12:41 PM cehteh: in sum it may have a few instrs more overhead, but shorter isr's without branches/loops are often worth that
12:42 PM landau: ok let me understand it...If I can get rid of the two for cycles it will be great!
12:42 PM cehteh: wait a moment i make some schematic code
12:44 PM landau: ohh thank you very very much!!
12:48 PM cehteh: https://paste.debian.net/1158474/
12:48 PM cehteh: thats all (sans debouncing)
12:48 PM landau: you see the delay there? I need it but I did not understand why it helps...without it if I connect a switch on the 0 position I get two signals i.e. 0 and 8...if I connect it to 8 i get 8 and 16 and I never understood why...
12:48 PM landau: thank you very much!!!
12:48 PM cehteh: and more a sketch of a idea, untested
12:49 PM landau: so at each call I scan one line
12:50 PM cehteh: yes
12:51 PM landau: you wrote PORTC
12:51 PM landau: what about PORTD?
12:51 PM cehteh: typo :D
12:51 PM landau: ah ok...and so what about PORTC that I use too?
12:51 PM * cehteh just hacked that into the paste w/o testing and while being distracted :D
12:52 PM landau: in the routine I have PORTC and PORTD too?
12:53 PM cehteh: yes was just mistyped reading from PORTC, writing to PORTD or?
12:54 PM landau: yes I set PORTD and I read PORTC
12:54 PM cehteh: its not meant to use unchecked, i just wantzed to show you the idea, so you need to understand it
12:54 PM landau: yes I need to understand it...
12:55 PM cehteh: possibly you need debouncing as well, tbd :D
12:56 PM landau: yes maybe I have to check this too
12:59 PM landau: I need to reset scanline to zero each 8 cycles right?
01:00 PM cehteh: no
01:00 PM landau: ok sorry...
01:01 PM cehteh: it just counts to 255 and overflows to 0 ... but &0b111 masks out the lower 3 bits giving 0..7 repeating intervals
01:02 PM landau: ahh that super!! very cleaver!
01:02 PM landau: now I got this first part... :D
01:03 PM landau: then i set PORTD, but I have to write the part that feels the changing
01:04 PM cehteh: yep, you need to addapt that to your needs, i think i guessed it right but when wrong you need to change the masking/shifting
01:05 PM cehteh: (or you connect it to PD0..2)
01:05 PM landau: yes I will check that for PORTD
01:06 PM cehteh: anyway when you hook up leds on the 4051 and programm the timer to go very slowly then you should be able to see a running light over all 8 outputs
01:07 PM landau: yes
01:07 PM landau: actually I connect switches
01:07 PM landau: it's a 8x8 keypad
01:08 PM cehteh: btw for simple debouncing you just store the keyboard_matrix twice once internal where you store the read state and one public once which you only change when the current read and the old state are equal
01:08 PM cehteh: gives a bit lag but debounces up and down and is really easy to implement
01:09 PM cehteh: (8ms lag shpuld be acceptable when you call that ISR every 1ms)
01:10 PM landau: so I need a keyboard_matrix to hold the old value to understand if it has changed
01:11 PM landau: because I want to send a UART signal only if one of the 64 inputs has been toggled ON or OFF
01:11 PM cehteh: rahter the otehr way around, currently you 'publish' reads as soon they become availabe in keyboard_matrix
01:12 PM cehteh: and that as well stores the old (last read) value
01:12 PM cehteh: you keep that, but keep that internal
01:13 PM landau: ok I will try to figure out all this...many many thanks!!
01:13 PM cehteh: then you have another keyboard_matrix (well the first one may be renamed to '*_internal') and only change that when the new read and the old one are identical
01:14 PM cehteh: well make it work without that first
01:14 PM cehteh: step by step
01:14 PM landau: yes I will try now...
01:18 PM landau: PORTD = (PORTD & ~0b111000) | ((scanline&0b111)<<3) what you do here is resetting the 0b00xxx000 and the assigning a 0 to 7 to xxx right? However I need to invert the 3 bit sequence... instead of having 000...001...so on I'd need 000...100...and so...do you know how I can invert the 3 bit sequence?
01:19 PM cehteh: why do you need that? isnt it irrelevant in what order you read the lines?
01:20 PM cehteh: actually when you send the keypresses over uart, then you can apply any kind of translation as well
01:20 PM landau: this will make easier to get the key number that goes from 0 to 64
01:21 PM landau: ah ok yes maybe I have to figure out how to do that
01:21 PM cehteh: you can decrement scanline or advance it any fancy way you want
01:22 PM cehteh: btw do you want to transmit keyup/keydown events?
01:22 PM cehteh: then you dont even have to store the 2nd keyboard matrix, just generate/queue such an event
01:22 PM landau: fsbus_snd(CID, key_index, 1, 3); and fsbus_snd(CID, key_index, 0, 3); will deal with the 0/1 transmission over the uart
01:23 PM landau: but I need a coherent index that goes from 0 to 64
01:23 PM cehteh: the isr puts in into an byte array
01:23 PM cehteh: when you want to send it over uart you can traverse that byte array in any way you want
01:24 PM landau: yes
01:24 PM landau: I would allocate keyboard_matrix[scanline&0x7] all to 1 because this is the initial state of all my 64 pins
01:25 PM cehteh: but i am just wondering if you need any events on key changed and possibly only transfer the changed keys?
01:25 PM cehteh: huh?
01:25 PM cehteh: ah keys pull to gnd?
01:25 PM landau: I need an event on the OFF->ON as well another event when ON->OFF
01:26 PM landau: yes just transmit the key change
01:27 PM cehteh: as i saied, then its best you dont publish the key matrix (only keep int internal for deboucing) but enqueue the event
01:27 PM landau: yes
01:38 PM landau: another stupid question for you...I have a 0b01000000 for instance...how to extract the position of the 1 in the byte, in this case 6
01:50 PM cehteh: count how much times you can right shift it until it becomes 0, but do you really need that?
01:51 PM cehteh: and there are more efficient algorihms for that, just google for 'bithacks' or so
01:51 PM landau: but I need a for cycle for that
01:51 PM cehteh: why do you need that?
01:51 PM landau: ok I will google bithacks thank!!
01:52 PM landau: I need it in order to get the number of the key
01:53 PM cehteh: do it the other way around
01:54 PM cehteh: actually multiple keys can be pressed together right?
01:54 PM cehteh: (does your matrix have diodes?)
01:55 PM landau: yes multiple keys are pressed at the same time (I do not have diodes...I had them but in the new design I deleted them as an engineer told me I don't need them but maybe I need them...)
01:56 PM landau: what do you mean by the other way around
02:26 PM landau: ok I got rid of the first for loop
02:28 PM landau: the second one I don't know I still need a way to find the position of the bit so I guess I need a for loop anyway
02:41 PM cehteh: ah .. 1) you still need the 2nd matrix to store the state, additional to debounce
02:42 PM cehteh: 2) when you are clever you manage to iterate only for pressed keys, which could abort early when no key is pressed
02:42 PM landau: ok
02:43 PM cehteh: ... ita all just some bit operations, to find out which key got changed (xor) and into what state (and)
02:44 PM landau: mmm ok I don't know if I will be able to do that
02:44 PM landau: but I will try to follow your suggestions
02:44 PM cehteh: you may reverse the logic what you store in the matrix (bit set means key pressed) .. thats one inversion thats pretty cheap
02:44 PM landau: many many thanks
02:44 PM landau: yes I can do that
02:47 PM landau: if you have time and you want to provide a pseudo-code, it will be easier for me..thanks!
02:50 PM landau: i could do the second for only if a key is pressed
02:51 PM cehteh: i am leaving asap
02:52 PM cehteh: i can try to make some very incomplete pseudocode
02:52 PM landau: ok thank you anyway!
02:52 PM landau: okok as you like...you really helped me a lot!!
03:12 PM cehteh: https://paste.debian.net/1158497/
03:13 PM cehteh: so .. not tested, certainly has bugs
03:13 PM cehteh: but i am done here :D
03:32 PM landau: ok
03:32 PM landau: thanks!!!
11:50 PM day_ is now known as day