This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

F28027 troubles with keypad scanning

Other Parts Discussed in Thread: LAUNCHXL-F28027, CONTROLSUITE

Hello!

I have C2000 Piccolo LAUNCHXL-F28027 and 4x4 matrix keypad(they are connected by GPIO) and I want to scan the keypad by timer tick, so I set timer interruption(with interval: ConfigCpuTimer(&CpuTimer0, 60, 50000)) and the keypad will be scanned when timer will ticked, here is the code of the function which will be called by timer tick(I deliberately simplified it for the tests):

interrupt void cpu_timer0_isr(void)
{	   
           CpuTimer0.InterruptCount++;

           PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;

	   if(GpioDataRegs.GPADAT.bit.GPIO4 == 0){

			 GpioDataRegs.GPADAT.bit.GPIO0 = 1;
			 DELAY_US(70);
			 if(GpioDataRegs.GPADAT.bit.GPIO4 == 1){
				 ch = 'q';
			 }
			 GpioDataRegs.GPADAT.bit.GPIO0 = 0;

			 GpioDataRegs.GPADAT.bit.GPIO1 = 1;
			 DELAY_US(70);
			 if(GpioDataRegs.GPADAT.bit.GPIO4 == 1){
				 ch = 'w';
			 }
			 GpioDataRegs.GPADAT.bit.GPIO1 = 0;
	   }

}


I have implemented the logic of the many keypad scanning samples (e.g. embedjournal.com/.../ ), but I get these problems:

  1. Scanning samples don't use delay after GPIO pin disabling, but I had to do this, because if I don't use it, then GPIO4 still equal to 0(the state does not have enough time to change). Is it right? How can I optimize it?
  2. After GPIO disabling I can't enable it again. "GpioDataRegs.GPADAT.bit.GPIO0 = 0;" command not seems like it's working. What am I doing wrong?
  3. If I will use the same algorithm, then my code will be very bulky. How can I optimize it?

So which mechanism I need to use for the right keyboard scanning?

  • Hi,

    When you're reading its DAT and while you're assigning it should be either set, clear or toggle.

    Regards,
    Gautam
  • Sorry, but it's not quite clear to me, can you provide a code example(because I think that I'm doing almost the same)?
    And what about delay and algorithm?
    Thanks!
  • Delay and algo seems fine but let the acknowledgement be at the last as suggested in sample codes. But your logic as such seems alright.

    Regards,
    Gautam
  • Hm... sorry but I really don't understand about which samples you say :)
    Can you provide a link to sample which solve item 2(After GPIO disabling I can't enable it again. "GpioDataRegs.GPADAT.bit.GPIO0 = 0;" command not seems like it's working)?

  • That's exactly why I suggested you to use: GPASET and GPACLEAR instead of GPADAT. Check the same out.
    You can find all the sample codes for your device here: C:\ti\controlSUITE\device_support\f2802x\v230\f2802x_examples_structs
    You need to download controlSuite for the same.

    Regards,
    Gautam
  • 1. If the keyboard has a lot of capacitance, you can probe the GPIO0 and GPIO4 lines with an oscilloscope or logic analyzer to see how long it takes the signal to propagate. Otherwise, the delay is probably coming from the synchronization logic. Try adding a cycle-based delay, like this:

    	asm(" RPT #16 || NOP");

    You can increase or decrease the number of cycles to figure out the exactly value needed. There's always a little propagation delay, so it's probably safest to double the value you get.

    2. Back to back writes to GPADAT interfere with each other due to the CPU pipeline. It's better to use GPASET and GPACLEAR to set and clear individual IOs. Here's some example code:

    	if(GpioDataRegs.GPADAT.bit.GPIO4 == 0){
    		GpioDataRegs.GPASET.bit.GPIO0 = 1;
    		DELAY_US(70);
    		if(GpioDataRegs.GPADAT.bit.GPIO4 == 1){
    			ch = 'q';
    		}
    		GpioDataRegs.GPACLEAR.bit.GPIO0 = 1;
    
    		GpioDataRegs.GPASET.bit.GPIO1 = 1;
    		DELAY_US(70);
    		if(GpioDataRegs.GPADAT.bit.GPIO4 == 1){
    			ch = 'w';
    		}
    		GpioDataRegs.GPACLEAR.bit.GPIO1 = 1;
    	}
    

    3. You can turn on compiler optimizations to reduce code size or improve performance. You can find the optimization settings in the CCS project build options.

    If you have to set a check a lot of GPIOs and want to reduce code size, you could use a for loop together with a look-up table for the keypad characters (and the GPIOs, if they're not sequential).

    I can't think of a good way to change the algorithm to improve execution time.

    If you're worried about spending a lot of time in the timer0 ISR, use the ISR to set a flag variable and have the main program loop check the flag variable.

  • The only remark is that it need to set GPACLEAR, instead clear:
    GpioDataRegs.GPACLEAR.bit.GPIO0 = 1;
    And how I can use "asm(" RPT #16 || NOP");"? If I just use this instead of delay, then I get nothing.
  • Yes, you're right. Sorry for the typo.

    The asm sequence I gave should add a repeated NOP instruction to the assembly output. Do you see those in the disassembly for the function? If not, are optimizations enabled? Also, make sure there's a space after the first quotation mark.

    You can go up to asm(" RPT #255 || NOP") for a 256-cycle delay.
  • Please check my question: e2e.ti.com/.../484566
    I have little time left, so I ask you, because I need very quick help, thanks!