0

pollkey() should be called every millisecond and tick(&timeloc) should be called every second and I don't have a thread library. The obvious way would be to do it with threads but now it seems that I need advice how to perform both the updates. The code I'm trying is

int main() {
    while (TRUE) {
        pollkey();
        puttime(&timeloc);
        delay(1);
        IOWR_ALTERA_AVALON_PIO_DATA(DE2_PIO_REDLED18_BASE, timeloc);
        if (RUN == 1) {
            tick(&timeloc);
            puthex(timeloc);
        }

    }
    return 0;
}

But I don't think that the above is 100 % correct. The entire program is

#include <stdio.h>
#include "system.h"
#include "altera_avalon_pio_regs.h"
extern void puttime(int* timeloc);
extern void puthex(int time);
extern void tick(int* timeloc);
extern void delay(int millisec);
extern int hexasc(int invalue);

#define TRUE 1
#define KEYS4 ( (unsigned int *) 0x840 )

int timeloc = 0x5957; /* startvalue given in hexadecimal/BCD-code */
int RUN = 0;

void pollkey() {

    int action = IORD_ALTERA_AVALON_PIO_DATA(DE2_PIO_KEYS4_BASE);
    putchar(action);
    if (action == 7) {
        timeloc = 0x0;
    } else if (action == 13) {
        RUN = 0;
    } else if (action == 14) {
        RUN = 1;
    } else if (action == 11) {
        tick(&timeloc);
    }
}

int main() {
    while (TRUE) {
        pollkey();
        puttime(&timeloc);
        delay(1);
        IOWR_ALTERA_AVALON_PIO_DATA(DE2_PIO_REDLED18_BASE, timeloc);
        if (RUN == 1) {
            tick(&timeloc);
            puthex(timeloc);
        }

    }
    return 0;
}

int hex7seg(int digit) {
    int trantab[] = { 0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00,
            0x10, 0x08, 0x03, 0x46, 0x21, 0x06, 0x0e };
    register int tmp = digit & 0xf;
    return (trantab[tmp]);
}

void puthex(int inval) {
    unsigned int hexresult;
    hexresult = hex7seg(inval);
    hexresult = hexresult | (hex7seg(inval >> 4) << 7);
    hexresult = hexresult | (hex7seg(inval >> 8) << 14);
    hexresult = hexresult | (hex7seg(inval >> 12) << 21);
    IOWR_ALTERA_AVALON_PIO_DATA(DE2_PIO_HEX_LOW28_BASE, hexresult);
}

int hex7seg2(int digit) {
    int trantab[] = { 0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00,
            0x10, 0x08, 0x03, 0x46, 0x21, 0x06, 0x0e };
    register int tmp = digit & 0xf0;
    return (trantab[tmp]);
}

I created subroutine for the delay, I think I might not change this:

        .equ    delaycount,     16911 #set right delay value here!
        .text                   # Instructions follow
        .global delay           # Makes "main" globally known

delay:  beq     r4,r0,fin       # exit outer loop

        movi    r8,delaycount   # delay estimation for 1ms

inner:  beq     r8,r0,outer     # exit from inner loop

        subi    r8,r8,1         # decrement inner counter

        br      inner

outer:  subi    r4,r4,1         # decrement outer counter
        br      delay


fin:    ret

The tick file is

extern void delay(int millisec);

/*
 * tick - update the time by adding one second
 * 
 * Parameter (only one): the address of the time variable.
 */
void tick( int * timeloc )
{
  /* Read time variable. */
  int tmp = * timeloc;

  tmp = tmp + 1; /* try a tick */

  /* if we ticked from 9 seconds to 10, adjust time properly */
  if( (tmp & 0x000f) == 0x000a ) tmp = tmp - 0x000a + 0x0010;

  /* if we ticked from 59 seconds to 60, adjust time properly */
  if( (tmp & 0x00f0) == 0x0060 ) tmp = tmp - 0x0060 + 0x0100;

  /* if we ticked from 9 minutes to 10, adjust time properly */
  if( (tmp & 0x0f00) == 0x0a00 ) tmp = tmp - 0x0a00 + 0x1000;

  /* if we ticked from 59 minutes to 60, adjust time properly */
  if( (tmp & 0xf000) == 0x6000 ) tmp = 0x0000;

  *timeloc = tmp;      /* update memory with new time value */
  delay(1000);
}

And it's in the tick file where the 1 second delay is. Can you think of a more correct way to achieve the result?

1 Answer 1

2

The standard approach to this is to track when was the last time a function was called and rerun it when enough time has passed.

#include <unistd.h>
#include <sys/time.h>

#define SLEEP_INTERVAL 200

struct timeval last_pollkey_call, last_tick_call, now, diff;
memset(&last_pollkey_call, 0, sizeof(last_pollkey_call));
memset(&last_tick_call, 0, sizeof(last_pollkey_call));

while(1) {
    gettimeofday(&now, NULL);

    timersub(&now, &last_pollkey_call, &diff);
    if (diff.tv_sec >= 1 || diff.tv_usec >= 1000) {
        pollkey();
        last_pollkey_call = now;
    }

    timersub(&now, &last_tick_call, &diff);
    if (diff.tv_sec >= 1) {
        tick();
        last_tick_call = now;
    }

    usleep(SLEEP_INTERVAL);
}

You can have as many events with as many different intervals as you like.

Sign up to request clarification or add additional context in comments.

2 Comments

I don't think I can do that until I'm sure that I can use the headers. I'm now thinking that I might try calling the C from the assembly delaysubroutine but it's not working.
@909Niklas Those headers are part of any standard libc. What C standard are you developing on?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.