NOOB Question

All technical discussions and projects around startKIT
Post Reply
NickE
Member
Posts: 10
Joined: Sun Dec 22, 2013 11:09 pm

NOOB Question

Post by NickE »

I have been experimenting with the startKIT for about a month and have managed to interface it with a Nokia 5110 LCD, ultrasonic distance monitor, MPU6050 6-axis gyroscope and accelerometer, HMC5883L digital compass, uart, and SPI to Raspberry Pi. I have spend many hours pouring over the documentation all over the Xmos site. So, I thought I was gaining an understanding of how to use the startKIT (and possible XS1 devices in general). But I guess I don't understand it very well at all.

Are ports that are designated as "in" ports always have default initial values of high (1)? If so, can this be changed?

Just for fun, I am trying to interface to a 16 switch matrix keyboard. This is a pretty trivial task (except for the debounce) on the arduino, pic, and even the Raspberry Pi. It has four "row" lines and four "column" lines. Setting each row line high one at a time, and scanning the four column lines for each row line. By knowing which row is set and detecting which column line(s) is high for that row set, allows you to determine which button(s) are pressed.

I am using 4C and 4D for the rows and columns on the J7 header. So essentially, I have in 4bit "in" port connected to a 4 bit "out" port with a matrix keyboard in between.

Ok, since the startKIT "in" port seems to be default high, I am setting each row low one at a time and scanning the four column lines to see which ones are low. Seems like it should work, but it doesn't. I admit that I am confused about the internal pull up and pull down resistors, how they are set on default, and how to change them if they need to be otherwise.

Any insight would be appreciated.

Thank you!


User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am
Contact:

Post by segher »

The pulldowns inside the chip are not strong enough to drive
anything external. Just put some pulldown resistors on your
columns and drive one row high at a time, and things should
work. You didn't say what happened without the resistors btw ;-)
NickE
Member
Posts: 10
Joined: Sun Dec 22, 2013 11:09 pm

Post by NickE »

Thank you for the answer.

I realized the problem: I just received this cheap matrix keypad that has 16 small pushbutton switched soldered to a pcb. I did some tests with a multimeter and with a magnifying glass, discovered that legs of three switches were unsoldered and a couple more had bad solder joints. (oh, well, it was cheap). Now it seems to work fine.

I guess the question that still remains is if the "out" ports are sufficient to safely drive the "in" ports without additional resistors added?
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am
Contact:

Post by segher »

Yes, outputs can drive inputs directly just fine. For high-speed
signals you can put a small resistor in-line to control rise time,
but for low-speed (as you have) you don't need to bother.

So it works now?
NickE
Member
Posts: 10
Joined: Sun Dec 22, 2013 11:09 pm

Post by NickE »

Yes, I can read the keys fine now. I am experimenting with debounce methods now. When I have one that does the job well, I will convert the test code into a module.
User avatar
infiniteimprobability
XCore Legend
Posts: 1126
Joined: Thu May 27, 2010 10:08 am
Contact:

Post by infiniteimprobability »

I am experimenting with debounce methods now.
I have found taking 5 or so consecutive samples at around 10ms apart, and checking they are all identical, is pretty reliable.

I bet there are many more ways of doing this!

Here's one I used for a recent project - it uses pinsneq to look for a port change and will only call a "button changed" method after 5 x 10ms of no bouncing.. Note it is combinable because it hardly stress a single core - so can be combined with loads of other stuff (in my case an LED matrix driver).

Code: Select all

[[combinable]]
void buttons(server interface buttons i_buttons, in port p_buttons){
    int button_val, button_after, press_time, debounce = 0;
    timer t;
    set_port_pull_down(p_buttons);      //Put unused bits into know state with weak pull down
    p_buttons :> button_val;            //Get initial port value
    while(1){
        select{
            //Fires if port value changes. Starts debounce process
            case p_buttons when pinsneq(button_val) :> button_val:
                t :> press_time;
                debounce = 1;
                break;

            //If debounce has started, take several samples. Register button changed if n consequitive the same
            case (debounce > 0) => t when timerafter(press_time + (DEBOUNCE_PERIOD / DEBOUNCE_SAMPLES)) :> void:
                p_buttons :> button_after;

                if (button_val == button_after){
                    debounce++;
                    if (debounce == DEBOUNCE_SAMPLES){
                        i_buttons.button_changed(); //Notify client that buttons have changed
                        debounce = 0;
                    }
                }
                else debounce = 0;
                t :> press_time;
                break;

            //Return button value
            case i_buttons.get_buttons() -> unsigned return_val:
                return_val = button_after;
                break;
        }
    }
}
Here's the prototype of the interface and the defines

Code: Select all

#define DEBOUNCE_PERIOD     5000000 //50ms
#define DEBOUNCE_SAMPLES    5       //5 samples at 50/5 = 10 ms intervals

interface buttons{
    [[notification]] slave void button_changed(void);
    [[clears_notification]] unsigned get_buttons(void);
};
Last edited by infiniteimprobability on Fri Feb 07, 2014 4:44 pm, edited 1 time in total.
Reason: missing defines
Post Reply