Forum Index
HomeZBasic Home   Forum RulesForum Rules   Forum FAQForum FAQ   MemberlistMemberlist   UsergroupsUsergroups   RSS FeedRSS Feed
Site SearchSite Search   LinksLinks   DownloadDownload   Digests and SubscriptionsDigests and Subscriptions
ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in   RegisterRegister
How to read in a byte
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Forum Index -> ZBasic Language
Author Message
Paul Lamar



Joined: 14 May 2010
Posts: 46

Posted: 10 July 2010, 19:15 PM    Post subject: How to read in a byte Reply with quote

This might be a really stupid question.
How do I read a byte in from a port name?

Paul Lamar
Back to top
dkinzer
Site Admin


Joined: 03 Sep 2005
Posts: 2593
Location: Portland, OR

Posted: 10 July 2010, 20:11 PM    Post subject: Re: How to read in a byte Reply with quote

Paul Lamar wrote:
How do I read a byte in from a port name?
To manipulate the full width of a port you must refer to the appropriate I/O register. For example, to read the logic value present at the pins of PortD you use Register.PIND.

On mega-based devices, each I/O port comprises three registers: PINx, PORTx and DDRx, where x is replaced by a port letter, e.g. A, B, C, etc. The bits of DDRx (Data Direction Register) control whether the corresponding pin is an input (zero) or an output (one). The bits of the PORTx register control two different things depending on whether the corresponding pins is configured to be an input or an output. If an input, the PORTx bit enables the pullup resistor and if an output it controls the state of the pin. Lastly, the PINx register provides a way to read the logic value present on the pins, irrespective of whether the individual pins are inputs or outputs. On newer mega devices, writing a 1 to a bit of the PINx register will toggle the state of the corresponding PORTx bit.

The information about the port registers can be found in the datasheet for the particular mega processor used on your ZX device. The datasheets are available on the Downloads Page as well as at the Atmel site.
Back to top
Paul Lamar



Joined: 14 May 2010
Posts: 46

Posted: 11 July 2010, 10:42 AM    Post subject: Reply with quote

Thanks Don.

I notice you discuss Register.PIND starting on page 63 of your ZBasic Language Reference Manual.

Could you give me an example of reading in a byte for PORTA using Register.XXXXX on
the 1280n?

I understand the concept of a data direction register. I just don't know how to set things up in ZBasic.

What do you mean by the term "control program"?

Which ports will affect the "control program" if modified?

See the attachement.

Paul Lamar



ZX-1280n-Registers.jpg
 Description:

Download
 Filename:  ZX-1280n-Registers.jpg
 Filesize:  81.92 KB
 Downloaded:  1630 Time(s)

Back to top
dkinzer
Site Admin


Joined: 03 Sep 2005
Posts: 2593
Location: Portland, OR

Posted: 11 July 2010, 15:17 PM    Post subject: Reply with quote

Paul Lamar wrote:
Could you give me an example of reading in a byte for PORTA using Register.XXXXX on the 1280n?
Code:
Dim b as Byte
b = Register.PinA

Paul Lamar wrote:
I understand the concept of a data direction register. I just don't know how to set things up in ZBasic.
If you wanted to make all 8 bits of PortA outputs, you could call PutPin() eight times or you could simply write
Code:
Register.DDRA = &Hff
Similarly, all 8 bits can be made inputs (the post-reset state) by writing zero to the DDR.

Paul Lamar wrote:
What do you mean by the term "control program"? Which ports will affect the "control program" if modified?
The control program refers to the interpreter that runs on VM devices. The smaller VM devices store the user program in an external EEPROM that is accessed via the SPI bus. On these devices, if you were to change the direction of the I/O pins used for the SPI interface you could prevent the SPI accesses from working correctly.

This is less of a problem on native mode devices but it is still possible to inadvertently change the state of I/O pins that are needed for other purposes. For example, if you call OutputCapture() in one task and then in another task you inadvertently change the direction of the I/O pin used by OutputCapture() you will cause it to fail. What this means is that you must carefully consider the effect of manipulating the registers directly to avoid changing bits that you didn't intend to change.

Note that the SetBits() subroutine can be used to manipulate a subset of the bits in a register. For example, if you wanted to set the direction of the four least significant bits of PortA while leaving the upper four bits unchanged you could write:
Code:
Call SetBits(Register.DDRA, &H0F, &H05)
This would make bits 0 and 2 outputs and bits 1 and 3 inputs. The advantage of using SetBits() is that it guarantees that the required read-modify-write operation is atomic. You could implement the same functionality thusly:
Code:
Atomic
  Register.DDRA = (Register.DDRA And &HF0) Or &H05
End Atomic
Back to top
Paul Lamar



Joined: 14 May 2010
Posts: 46

Posted: 11 July 2010, 17:44 PM    Post subject: Reply with quote

Thanks Don,

Perhaps you could extend ZBasic and write a PEEK(Port) and POKE(Port) by first reading
what the port set up is, save it and restore that after the instruction executes. It will add time
no doubt but a warning to that effect in the manual would be OK.

Paul Lamar
Back to top
dkinzer
Site Admin


Joined: 03 Sep 2005
Posts: 2593
Location: Portland, OR

Posted: 11 July 2010, 18:41 PM    Post subject: Reply with quote

Paul Lamar wrote:
Perhaps you could extend ZBasic and write a PEEK(Port) and POKE(Port) by first reading what the port set up is, save it and restore that after the instruction executes.
I don't understand the functionality that you would like to have added. What, in general terms, would PEEK(port) and POKE(port) do and can you give examples of using them to accomplish specific tasks?
Back to top
Paul Lamar



Joined: 14 May 2010
Posts: 46

Posted: 11 July 2010, 19:20 PM    Post subject: Reply with quote

There are some hardware devices in the world that communicate with a computer
8 bits at a time through a parallel interface. The best and most widely used is
the famous Centronics printer interface. Hard drives used to be parallel before SATA
although hard drives made little sense as the data had to be written and read one bit
at a time anyway unless one was using 8 sides of four magnetic disks.

Arguably a parallel interface is easier and quicker than a serial interface where data goes out one bit at a time. It is certainly easer for the BASIC programmer to PEEK or POKE a port or memory location as a lot of data manipulation is done 8 bits at a time. A person designing such a parallel device has an easier time of it rather than adding the hardware required to serialise data that started life as parallel data.

There are two types of processors. Those that handle I/O as just another
memory location and those that use dedicated registers for I/O. The first example is the
Motorola, Mos Technology (Early Apple) and Intel processors and those that use dedicated registers. such as (apparently) the Atmel perhaps among others.

In the first group the ports were in general automatically bi directional as are memory locations. These used a read write line that goes along with the PEEK or POKE. DDR's were not always necessary but could be accommodated. This was called memory map I/O.

Paul Lamar
Back to top
GTBecker



Joined: 18 Jan 2006
Posts: 472
Location: Cape Coral

Posted: 11 July 2010, 19:54 PM    Post subject: Ouch! Reply with quote

Paul, forgive me, please; this will sting a little.

Did you build and engage a time machine in 1980 - and inadvertently return to the future? Where have you been for the last 30 years?

To invite someone to implement the likes of a Centronics port today is bizarre. To lecture on memory mapping is insulting. Although machines remain massively parallel within the chip, speed has replaced most external parallel buses. Serializing parallel data today is easy and cheap - and done onboard the processors; we no longer need 40-pin 8250 UARTs to do it, nor the FIFO, since memory abounds.

I am 63; I suspect you are near that, and I still respect my elders. I loved the 1401 I started on and I still have my IBM printer rule and flowchart template, but I no longer use them; time has elapsed. Truly, have you only recently rejoined technology?
Back to top
Paul Lamar



Joined: 14 May 2010
Posts: 46

Posted: 11 July 2010, 21:03 PM    Post subject: Reply with quote

No insult intended Don.

I am sorry you see it that way.

It does not sting as I respect differences of opinion.

You have not changed my mind.

Paul Lamar
Back to top
Paul Lamar



Joined: 14 May 2010
Posts: 46

Posted: 11 July 2010, 21:22 PM    Post subject: Reply with quote

Here is another project I am working on.
Note the anything I/O card is massively parallel.

These boards are widely used world wide to control NC
machine tools using EMC software


Paul Lamar



Toms-conversion_sm.jpg
 Description:
 Filesize:  76.23 KB
 Viewed:  2591 Time(s)

Toms-conversion_sm.jpg



Mesa-7i33.jpg
 Description:

Download
 Filename:  Mesa-7i33.jpg
 Filesize:  94.38 KB
 Downloaded:  1621 Time(s)


Mesa-5i20.jpg
 Description:

Download
 Filename:  Mesa-5i20.jpg
 Filesize:  96.03 KB
 Downloaded:  913 Time(s)


control-block-diag5S.jpg
 Description:

Download
 Filename:  control-block-diag5S.jpg
 Filesize:  66.27 KB
 Downloaded:  1621 Time(s)

Back to top
dkinzer
Site Admin


Joined: 03 Sep 2005
Posts: 2593
Location: Portland, OR

Posted: 11 July 2010, 22:07 PM    Post subject: Reply with quote

Paul Lamar wrote:
No insult intended Don.
Perhaps you're responding to a reply from Tom.

As far as the PEEK and POKE are concerned, if the 8-bit port remains configured as all inputs or all outputs then simply referring to Register.PINx or Register.PORTx, respectively is all that is needed to read a byte from or write a byte to the port. If you need the port to be bi-directional, then it is only slightly more involved.
Code:
' to write a port
Register.DDRA = &HFF  ' set the direction
Register.PortA = val

' to read a port
Register.DDRA = &H00  ' set the direction
Register.PortA = &H00 ' turn off pullups
val = Register.PinA

I can't think of a good way to encapsulate these in a simple subroutine and function to generalize them using ZBasic statements only but it could be done for most mega-based native mode devices using some C code like this:
Code:
'-----------------------------------------------------------------------
'
' C routines to read and write ports.  These do not work on older
' mega devices (e.g. the mega128) because the PIN, DDR and PORT
' registers are not sequential nor do they work on the xmega devices
' because they have a different I/O port structure.
'
' On newer mega devices, the three registers associated with an I/O
' port are arranged sequentially: PINx, DDRx and PORTx.
'
#c

// low-level ZX Library routine to get the base address of a port 
uint8_t *getPortAddr(uint8_t idx);

// function to make a port all outputs and write a value to it
void
_writePort(uint16_t portIdx, uint8_t val)
{
    // get the port address, check for a valid port
    uint8_t *addr = getPortAddr(portIdx);
    if (addr != NULL)
    {
        addr[1] = 0xff;  // make all bits outputs
        addr[2] = val;   // write the PORTx register
    }
}

// function to make a port all inputs, turn off the pullup resistors
// and then read the PINx register.
uint8_t
_readPort(uint16_t portIdx)
{
    uint8_t val = 0;

    // get the port address, check for a valid port
    uint8_t *addr = getPortAddr(portIdx);
    if (addr != NULL)
    {
        addr[1] = 0;     // make all bits inputs
        addr[2] = 0;     // turn off pullup resistors
        val = addr[0];   // read the PINx register
    }
    return(val);
}
#endc
'-----------------------------------------------------------------------

' an enumeration to define the port index values: A=0, B=1, etc.
Enum PortType
  PortA = 0
  PortB
  PortC
  PortD
  ' add other ports as needed
End Enum

' declare the ZBasic interface to the C functions
Declare Function ReadPort(ByVal port as PortType) as Byte Alias "_readPort"
Declare Sub WritePort(ByVal port as PortType, ByVal val as Byte) Alias "_writePort"

Dim b as Byte

Sub Main()
    b = ReadPort(PortA)
    Call WritePort(PortB, &H55)
End Sub
Back to top
Paul Lamar



Joined: 14 May 2010
Posts: 46

Posted: 11 July 2010, 22:18 PM    Post subject: Reply with quote

One other thing Don and then I'll shut up.

It took 2.5 usec to set pin 12 low and 2.5 usec to set it high.
Basically a parallel operation.

However it took 12.5 usec to send out one ASCII character
through the USB serial port using debug.print.

Now if you had half a dozen USB ports on the 1280n board I might change my
mind Smile There is only one and I have half a dozen things I want to control.

I rest my case.

Paul Lamar



serial-port-test.jpg
 Description:

Download
 Filename:  serial-port-test.jpg
 Filesize:  66.86 KB
 Downloaded:  1619 Time(s)


IMG_0662.JPG
 Description:

Download
 Filename:  IMG_0662.JPG
 Filesize:  60.86 KB
 Downloaded:  1621 Time(s)

Back to top
stevech



Joined: 23 Feb 2006
Posts: 688

Posted: 12 July 2010, 0:46 AM    Post subject: Reply with quote

that 2.5uSec is in the native mode (not VM)?
Back to top
Paul Lamar



Joined: 14 May 2010
Posts: 46

Posted: 12 July 2010, 2:04 AM    Post subject: Reply with quote

The compiler. Not the interpreter.

Paul Lamar

www.rotaryeng.net
Back to top
Paul Lamar



Joined: 14 May 2010
Posts: 46

Posted: 13 July 2010, 21:08 PM    Post subject: Reply with quote

Thanks Don,

Worked like a charm.

It is at least ten times faster than the serial USB port because
if you comment out "val = Register.PINH" the scope trace
hardly changes. That means just taking a bit low and then high
takes at least 10 usec. while reading in 8 bits parallel probably
takes much less than one usec. I could do ten in a row
and see what happens but I am very very happy with less
than a usec.

This greatly simplifies my hardware on the sending end as no
need to serialise and handle the serial hand shaking.

Thanks for your help Don.

Paul Lamar
www.rotaryeng.net



peek-time-test.JPG
 Description:

Download
 Filename:  peek-time-test.JPG
 Filesize:  53.49 KB
 Downloaded:  1619 Time(s)


IMG_0663.JPG
 Description:

Download
 Filename:  IMG_0663.JPG
 Filesize:  80.39 KB
 Downloaded:  1615 Time(s)


IMG_0665.JPG
 Description:

Download
 Filename:  IMG_0665.JPG
 Filesize:  56.55 KB
 Downloaded:  1616 Time(s)

Back to top
Display posts from previous:   
Post new topic   Reply to topic    Forum Index -> ZBasic Language Time synchro. with the server - Timezone/DST with your computer
Goto page 1, 2  Next
Page 1 of 2

 


All content Copyright © 2005-2012 Elba Corp. All Rights Reserved.
Opinions expressed in posts are those of the author and not necessarily those of Elba Corp.
Powered by phpBB © 2001, 2005 phpBB Group