initial commit
authorJohn Tsiombikas <nuclear@mutantstargoat.com>
Tue, 23 Jul 2019 16:38:24 +0000 (19:38 +0300)
committerJohn Tsiombikas <nuclear@mutantstargoat.com>
Tue, 23 Jul 2019 16:38:24 +0000 (19:38 +0300)
Makefile [new file with mode: 0644]
pulser.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..9d9159f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,11 @@
+obj = pulser.o
+bin = pulser
+
+CFLAGS = -pedantic -Wall -g
+
+$(bin): $(obj)
+       $(CC) -o $@ $(obj) $(LDFLAGS)
+
+.PHONY: clean
+clean:
+       rm -f $(obj) $(bin)
diff --git a/pulser.c b/pulser.c
new file mode 100644 (file)
index 0000000..6362d67
--- /dev/null
+++ b/pulser.c
@@ -0,0 +1,132 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <assert.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#define IOBASEADDR             0x3f000000
+#define IOSIZE                 16777216
+
+#define IOREGADDR(x)   ((x) | IOBASEADDR)
+
+#define REG_GPFSEL0            *((volatile uint32_t*)IOREGADDR(0x200000))
+#define REG_GPFSEL1            *((volatile uint32_t*)IOREGADDR(0x200004))
+#define REG_GPFSEL2            *((volatile uint32_t*)IOREGADDR(0x200008))
+#define REG_GPSET0             *((volatile uint32_t*)IOREGADDR(0x20001c))
+#define REG_GPSET1             *((volatile uint32_t*)IOREGADDR(0x200020))
+#define REG_GPCLR0             *((volatile uint32_t*)IOREGADDR(0x200028))
+#define REG_GPCLR1             *((volatile uint32_t*)IOREGADDR(0x20002c))
+
+#define FSEL_OUT(x)            (1 << (((x) % 10) * 3))
+
+void print_usage(const char *argv0);
+
+int npulses = 1;
+int freqhz = 1;
+int duty = 128;        /* duty cycle 0-255 */
+int pin = 24;
+
+int main(int argc, char **argv)
+{
+       int i, fd;
+       void *ptr;
+       long ontime, offtime;
+
+       for(i=1; i<argc; i++) {
+               if(argv[i][0] == '-') {
+                       if(argv[i][2] == 0) {
+                               switch(argv[i][1]) {
+                               case 'n':
+                                       if(!argv[++i] || (npulses = atoi(argv[i])) < 1) {
+                                               fprintf(stderr, "-n must be followed by the number of pulses\n");
+                                               return 1;
+                                       }
+                                       break;
+
+                               case 'f':
+                                       if(!argv[++i] || (freqhz = atoi(argv[i])) < 1) {
+                                               fprintf(stderr, "-f must be followed by the pulse frequency\n");
+                                               return 1;
+                                       }
+                                       break;
+
+                               case 'd':
+                                       if(!argv[++i] || (duty = atoi(argv[i])) < 1 || duty >= 256) {
+                                               fprintf(stderr, "-d must be followed by the duty cycle: 1-255\n");
+                                               return 1;
+                                       }
+                                       break;
+
+                               case 'h':
+                                       print_usage(argv[0]);
+                                       return 0;
+
+                               default:
+                                       fprintf(stderr, "invalid option: %s\n", argv[i]);
+                                       print_usage(argv[0]);
+                                       return 1;
+                               }
+                       } else {
+                               fprintf(stderr, "invalid option: %s\n", argv[i]);
+                               print_usage(argv[0]);
+                               return 1;
+                       }
+               } else {
+                       fprintf(stderr, "unexpected argument: %s\n", argv[i]);
+                       print_usage(argv[0]);
+                       return 1;
+               }
+       }
+
+
+       if((fd = open("/dev/mem", O_RDWR)) == -1) {
+               perror("failed to open /dev/mem");
+               return 1;
+       }
+       if((ptr = mmap((void*)IOBASEADDR, IOSIZE, PROT_READ | PROT_WRITE,
+                                       MAP_SHARED | MAP_FIXED, fd, IOBASEADDR)) == (void*)-1) {
+               perror("failed to map IO space");
+               return 1;
+       }
+       assert(ptr == (void*)IOBASEADDR);
+
+       ontime = duty * 1000000 / (freqhz * 256);
+       offtime = 1000000 / freqhz - ontime;
+
+       printf("%d pulses, %d hz, %d/256 duty cycle\n", npulses, freqhz, duty);
+       printf("timing: %ldus on, %ldus off\n", ontime, offtime);
+
+       REG_GPCLR0 = 1 << pin;
+       if(pin < 10) {
+               REG_GPFSEL0 |= FSEL_OUT(pin);
+       } else if(pin < 20) {
+               REG_GPFSEL1 |= FSEL_OUT(pin);
+       } else if(pin < 30) {
+               REG_GPFSEL2 |= FSEL_OUT(pin);
+       }
+
+       for(i=0; i<npulses; i++) {
+               REG_GPSET0 = 1 << pin;
+               usleep(ontime);
+               REG_GPCLR0 = 1 << pin;
+               usleep(offtime);
+       }
+
+       REG_GPCLR0 = 1 << pin;
+
+       munmap(ptr, IOSIZE);
+       close(fd);
+       return 0;
+}
+
+void print_usage(const char *argv0)
+{
+       printf("Usage: %s [options]\n", argv0);
+       printf("Options:\n");
+       printf(" -n: number of pulses to emit (default: 1)\n");
+       printf(" -f: frequency of pulses in hz (default: 1)\n");
+       printf(" -d: duty cycle [1, 255] (default: 128)\n");
+       printf(" -h: print usage and exit\n");
+}