reading status inport

Download pre-release library modules and new examples to use with Astrobe for LPC2000. Forum members can also upload their own source code examples.
Post Reply
Oberoid
Posts: 18
Joined: Fri Jan 28, 2011 8:57 pm
Location: Amsterdam, Netherlands

reading status inport

Post by Oberoid » Mon Feb 21, 2011 3:01 pm

Hi,
does anyone can explain me how can i read the status of an input port.
I have several micro switches attached to my LPC2138 AE edu board and I would like to use them.
Is there a status register wich can be read?

Greets,
F.P.

cfbsoftware
Site Admin
Posts: 545
Joined: Fri Dec 31, 2010 12:30 pm
Contact:

Re: reading status inport

Post by cfbsoftware » Tue Feb 22, 2011 12:23 am

The five pushbuttons on the EA LPC2138 board are connected to pins P0.14 and P1.16-19.

You can access these via the GPIO registers which are defined as IOPIN0 (for pins P0.*) and IOPIN1 (for pins P1.*) in the Astrobe LPC2138 module.

The status of each bit in the register corresponds to the status of one of 32 pins. e.g. the code to check if P1.17 is pressed would look something like this:

Code: Select all

IMPORT LPC := LPC2138, SYSTEM, Main;
...
IF SYSTEM.BIT(LPC.IOPIN1, 17) THEN ...
Refer to Chapter 8 GPIO in the NXP LPC2138 User Manual (UM10120) for more details. If you haven't already got a copy download it from the NXP support site:

http://ics.nxp.com/support/documents/?search=UM10120

Oberoid
Posts: 18
Joined: Fri Jan 28, 2011 8:57 pm
Location: Amsterdam, Netherlands

Re: reading status inport

Post by Oberoid » Tue Feb 22, 2011 9:24 am

Now I now where I can use the SYSTEM.BIT procedure for.
I was trying out SET operations on the status register but maybe this is easier and clearer.

The tutorial of Embedded artists is using a shift register and I would like to explore its functionality by manipulating its control lines myself.
Polling vs interrupt driven programming is another topic that i would like to investigated with buttons.

Thanks for the answer.. I will try it out.

Greets,
F.P.

Oberoid
Posts: 18
Joined: Fri Jan 28, 2011 8:57 pm
Location: Amsterdam, Netherlands

Re: reading status inport

Post by Oberoid » Sat Feb 26, 2011 11:03 pm

I am intrigued by the article "SET: A neglected data type, and its compilation for the ARM" (Wirth 2008) https://www.astrobe.com/wirth/SETs.pdf and try to apply set types to io registers.
I found this example code in the specification of the SYSTEM.mod of the Oberon System.
http://www-old.oberon.ethz.ch/SYSTEM.html

Code: Select all

PROCEDURE Testbit*; (* Test the presence of a specific bit in scr *) 
 BEGIN 
   IF SYSTEM.BIT(SYSTEM.ADR(scr), 6) THEN END;  (* first approach *)
   IF 6 IN SYSTEM.VAL(SET, scr) THEN END;  (* better approach *) 
    (* or even better, declare scr2 as a SET to starts with *)
   SYSTEM.GET(SYSTEM.ADR(value), SYSTEM.VAL(SET, scr2));  (* from memory *) 
   IF 6 IN scr2 THEN END;
END Testbit; 
However, I'm wondering if a procedure, something like Ports.In(port: PORT, VAR status: Status), could be useful.
As a beginner I want to check or set the status of an Port by using the Ports name, eg P101,as a value parameter.
Also the precondition that the port to be read is set as an In port should be met. Maybe with an global variable: Ports.Done a successful read action can be verified.

What would you think is the wisest approach to reading ports: the SYSTEM.BIT, the SYSTEM.GET(SYSTEM.ADR(value), SYSTEM.VAL(SET, scr2)) or the Ports.In(p101, status) way?

cfbsoftware
Site Admin
Posts: 545
Joined: Fri Dec 31, 2010 12:30 pm
Contact:

Re: reading status inport

Post by cfbsoftware » Sun Feb 27, 2011 4:30 am

Some points to be considered before implementing such a module:
  • The number of ports that are available depends on the LPC2xxx device being targeted. A general solution would need to support from 1 to 4 ports.
  • 4 ports with 32 pins each gives 128 possible values. A system of names P000 to P331 would be unwieldy. I would suggest two parameters: port number and pin number. Port number could be named constants if preferred e.g.

    Code: Select all

    CONST
      Port0* = 0;
      Port1* = 1;
      Port2* = 2;
      Port3* = 3;
    However, I see little value in identifying a pin by anything else but its number 0..31.
  • User-defined types in Oberon-07 are restricted to pointers, arrays and records. Type aliases (e.g. the proposed types Port and Status) are not supported.
  • Some MCUs have fast IO port access (FIO) as well as the legacy (GPIO) system.
Possible precondition checks are:
  • Are the Port number and pin number in range?
  • Does the port exist on the current target?
  • Is the pin available for use as a GPIO pin on the current target? Too complex a check to be worth doing?
Note that IOPIN always returns the status of a pin whether it is defined as an input or output pin so it might only be necessary to check its direction when writing to it.

Given all of the above one possible approach is:

Code: Select all

GPIO.In(CONST portNo, pinNo: INTEGER; VAR value: BOOLEAN);
GPIO.Out(CONST portNo, pinNo: INTEGER; CONST value: BOOLEAN);
If you had a board with pushbuttons connected to pins 0.15 to 0.18 and you wanted them to control leds on pins 1.17 to 1.20 respectively you could write something like:

Code: Select all

    (* Untested! *)
    FOR pin := 15 TO 18 DO 
      led := pin + 2;
      GPIO.In(port0, pin, state);
      GPIO.Out(port1, led, state)
    END;
Without a GPIO module I would write it like this:

Code: Select all

   (* Untested! *)
    SYSTEM.GET(LPC.IOPIN0, port0);
    FOR pin := 15 TO 18 DO 
      led := pin + 2;
      IF pin IN port0 THEN 
        SYSTEM.PUT(LPC.IOCLR1, {led})
      ELSE
        SYSTEM.PUT(LPC.IOSET1, {led})
      END
    END
 
If realtime performance was a critical issue the latter solution would be preferable. Otherwise the choice would depend on the preferences of the individual programmer.

cfbsoftware
Site Admin
Posts: 545
Joined: Fri Dec 31, 2010 12:30 pm
Contact:

Re: reading status inport

Post by cfbsoftware » Sun Feb 27, 2011 11:53 pm

Oberoid wrote:I found this example code in the specification of the SYSTEM.mod of the Oberon System.

Code: Select all

(* or even better, declare scr2 as a SET to starts with *)
   SYSTEM.GET(SYSTEM.ADR(value), SYSTEM.VAL(SET, scr2));  (* from memory *) 
By definition SYSTEM features are highly platform/implementation-dependent. To avoid confusion you should always refer to the implementation-specific documentation of the Oberon system that you are curently targeting for information on how to use the SYSTEM features. In Astrobe v3.2 refer to Section 7.23 SYSTEM of the document "Oberon for LPC2000 Microcontrollers".

There you will see that the second parameter of SYSTEM.GET is of type <any basic type>. Hence the SYSTEM.VAL typecast is unnecessary. Typically in Astrobe, the first parameter to SYSTEM.GET is already an address e.g. one of the register address constants defined in the module LPC.mod. Hence the SYSTEM.ADR is not required either. Consequently in Astrobe code, typical examples of the use of SYSTEM.GET are:

Using INTEGER variables:

Code: Select all

(* Real Time Clock *)
VAR
  hours, minutes, seconds: INTEGER;
...
...
  SYSTEM.GET(LPC.HOUR, hours);
  SYSTEM.GET(LPC.MIN, minutes);
  SYSTEM.GET(LPC.SEC, seconds);
Using SET variables:

Code: Select all

(* GPIO pin configuration *)
VAR
  selection, direction: SET;
...
...
  (* Pins P0.16..P0.18, P0.26..P0.29 are configured for GPIO usage by clearing the relevant bits *)
  SYSTEM.GET(LPC.PINSEL1, selection);
  SYSTEM.PUT(LPC.PINSEL1, selection - {0..5, 20..27});
  (* Pins P0.16..P0.18, P0.26..P0.29 are configured as outputs by setting the relevant bits*)
  SYSTEM.GET(LPC.IODIR, direction);
  SYSTEM.PUT(LPC.IODIR, direction + {16..18, 26..29});

Post Reply