Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

#22 direct i/o access, set_bit, and clear_bit

open
nobody
None
7
2005-05-20
2005-05-20
scott
No

I am developing z80 code for a custom computer that I
have built. The 8255 I/O is at 0x00, the rom starts at
0x0000, and the ram starts at 0x8000. I was wondering
how to define a variable for direct access to I/O
ports. For example, here is how you do that in the
hi-tech z80 c compiler:

static port BYTE port_a @ 0x00;
static port BYTE port_b @ 0x01;

Also, I was wondering if there are set_bit and
clear_bit routines that make use of the z80 set and res
opcodes.

Discussion

  • scott
    scott
    2005-05-20

    • priority: 5 --> 9
     
  • scott
    scott
    2005-05-20

    • priority: 9 --> 7
     
  • Dominic Morris
    Dominic Morris
    2005-05-20

    Logged In: YES
    user_id=15738

    Memory mapped ports (eg for the gameboy) are supported by
    placement:

    extern unsigned char port_a @ 0x01;
    extern unsigned char port_b @ 0x02;

    For IO driven ports it's probably best to write an assembler
    function. There's no bit setting routines available
    unfortunately.

    Ports can't be done - you can easily write some inline
    assembler to do the trick though

     
  • Logged In: NO

    Alright, I wrote an inline function which is extremely
    inefficient. I was wondering if it would be possible to do a
    defined a macro to do the function, like this:
    #define set_io(DAT,PORT) #asm ld a,DAT ld c,PORT out
    (c),a #endasm
    But I do not know how to do that, here is the very inefficient
    function I wrote:
    void write_io(BYTE data, BYTE port) {
    #asm
    .tempdata defb 0
    ld hl,04h
    add hl,sp
    ld l,(hl)
    ld h,00h
    ld a,l
    ld (tempdata),a
    ld hl,02h
    add hl,sp
    ld l,(hl)
    ld h,00h
    ld a,l
    push bc
    ld c,a
    ld a,(tempdata)
    out (c),a
    pop bc
    #endasm
    }

    any idea on how to do the macro implementation? Thanks.

     
  • Dominic Morris
    Dominic Morris
    2005-05-20

    Logged In: YES
    user_id=15738

    Yup, this will only work for constants - the function method
    has the advantage of being able to take variables, but the
    macros will look like these:

    #define set_io(DAT,PORT)
    asm("ld\ta,"#DAT"\nld\tc,"#PORT"\nout\t(c),a\n")
    #define in_io(PORT)
    asm("ld\tc,"#PORT"\nin\ta,(c)\nld\tl,a\nld\th,0\n")

    The in_io puts the value into hl so it you can take the
    result of it and assign it to an integer variables.

    Actually (brain started working again!), in the rex library
    there's two functions called input8 and output8 which
    probably do what you want - take a look in the libsrc/rex

     
  • Logged In: NO

    Its alright if the port value is constant, but I need the data to
    be variable, like so:
    BYTE var;
    var=0x80;
    set_io(var,0x03);
    what changes need to be made to the macro?

     
  • scott
    scott
    2005-05-20

    Logged In: YES
    user_id=1281962

    Nevermind about the previous post, I got it to work. First I
    define the data globally: BYTE data;
    then in main() I do:
    set_io((_data),0x00);
    I could also modify the asm code to make the c code a bit
    more pleasing to the eye.

     
  • scott
    scott
    2005-05-20

    Logged In: YES
    user_id=1281962

    I have another question, how do I set the compiler so that
    variables are not placed below a certain memory address? My
    declared variables are being placed in the rom area.

     
  • scott
    scott
    2005-05-21

    Logged In: YES
    user_id=1281962

    I need to define access to a certain memory area, should I do:
    extern BYTE *screendata @ 0x8000;
    Whenever I do a memset() on the data, the data is not
    zeroed, so I think this define is incorrect. Any ideas?

     
  • Dominic Morris
    Dominic Morris
    2005-05-21

    Logged In: YES
    user_id=15738

    Right, variables can be placed starting at point in memory by specifying
    the -make-app flag to the compiler, this allows all variables to bunched up
    together across files in the project.

    In order to support this you need to change the startup code to start
    variables from that point - take a look at the embedded_crt0.asm file in the
    lib since that does something similar to what I think you're trying to
    achieve.

     
  • scott
    scott
    2005-05-24

    Logged In: YES
    user_id=1281962

    So how exactly do you use the -make-app flag to place
    variables above a certain memory location?

     
  • Dominic Morris
    Dominic Morris
    2005-05-25

    Logged In: YES
    user_id=15738

    The startup in lib/ defines a DEFVARS block at a certain
    address. The -make-app flag causes the compiler to place all
    variables within a DEFVARS in each compilation unit. At
    assembly/link time all the DEFVARS blocks are merged into a
    single one placed at the location specified in the crt0 code.