#include <stdio.h>
#include <stdint.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <semaphore.h>
#include "gpio.h"
#include "done.h"
#include "blink.h"#include <stdio.h>
#include <stdint.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <semaphore.h>
#include "gpio.h"
#include "done.h"
#include "blink.h"Full second in nanoseconds.
#define NANOSECOND 1000000000lInlined macro to make timeval.
#ifndef TIMESPEC_TO_TIMEVAL
#define TIMESPEC_TO_TIMEVAL(tv, ts) { \
(tv)->tv_sec = (ts)->tv_sec; \
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
}
#endifSemaphore. See assignment 3.
static sem_t block;
void blink_unblock(int signo) {
sem_post(&block);
}This is the same as in assignment 3, except that the GPIO code now uses
slightly different names for the GPIOs, namely LED1 instead of GPIO87,
and LED2 instead of GPIO89. This reflects the fact that this code can
run on other boards than the PocketBeagle, which might have the LEDs on
other GPIO pins.
void *blink_at_frequency(void * _)
{
enum Direction led1_dir = gpio_get_dir(LED1);
enum Direction led2_dir = gpio_get_dir(LED2);
gpio_set_dir(LED1, OUT);
gpio_set_dir(LED2, OUT);
gpio_set_value(LED1, OFF);
gpio_set_value(LED2, OFF);
int sem_good = 1;
struct sigaction act; {
act.sa_handler = blink_unblock;
act.sa_flags = 0;
sigfillset(&act.sa_mask);
}
if (sem_init(&block, 0, 0) < 0) {
sem_good = 0;
perror("Could not initialize semaphore");
done = 1;
} else {
sigaction(SIGALRM, &act, NULL);
}
struct timespec sleeptime;
struct itimerval timeout = {0};
double duty;
while (!done) {
duty = (1.0 / frequency) * NANOSECOND;
sleeptime.tv_sec = (uint32_t)(duty / NANOSECOND);
sleeptime.tv_nsec = ((uint64_t)duty) % NANOSECOND;
enum Value d1 = gpio_get_value(LED1);
enum Value d1_next = d1 == OFF ? ON : OFF;
enum Value d2_next = d1 == OFF ? OFF : ON;
gpio_set_value(LED1, d1_next);
gpio_set_value(LED2, d2_next);
TIMESPEC_TO_TIMEVAL(&timeout.it_value, &sleeptime);
setitimer(ITIMER_REAL, &timeout, NULL);
sem_wait(&block);
}
if (sem_good) {
sem_destroy(&block);
}
gpio_set_value(LED1, OFF);
gpio_set_value(LED2, OFF);
gpio_set_dir(LED1, led1_dir);
gpio_set_dir(LED2, led2_dir);
return NULL;
}