diff options
| -rw-r--r-- | example.c | 72 | ||||
| -rw-r--r-- | host/client.c | 65 | ||||
| -rw-r--r-- | main.c | 124 |
3 files changed, 118 insertions, 143 deletions
@@ -36,38 +36,55 @@ void send_str(const char *s); uint8_t recv_str(char *buf, uint8_t size); void parse_and_execute_command(const char *buf, uint8_t num); -// Very simple character echo test int main(void) { - int changed = 0; + int changed = 0, val; int port = 'B' - 'A'; - int pin = '0' - '0'; - int val; - CPU_PRESCALE(0); + int pin = 1 << ('0' - '0'); + int latency = 0; + + CPU_PRESCALE(0x00); // 16 MHz usb_init(); LED_CONFIG; while (!usb_configured()) /* wait */ ; _delay_ms(1000); - - LED_ON; - + CPU_PRESCALE(0x04); // 1 MHz uint8_t *portload = 0x20 + port * 3; + *portload &= ~pin; - *(uint8_t *)(0x21 + port * 3) &= ~(1 << pin); - + TCCR1B |= (1 << CS10); // Set timer1 to 1 microsecond steps while (1) { - val = *portload & (1 << pin); -// usb_serial_putchar(val + '0'); - if ((val == 1) && (changed == 0)) { - changed = 1; - usb_serial_putchar(val ? '1' : '0'); - LED_ON; - } else if ((val == 0) && (changed == 1)) { + val = *portload & pin; + if ((val == 0) && (changed == 1)) { + /* trailing edge of pulse. + * + * I track the 1->0 transition rather than + * 0->1 because it's sharper. + */ + int count; + count = TCNT1; // read timer + if (count < 15000) + /* ignore spurious pulses. If I don't + * do this, for some reason I'll see a + * bunch of half-width pulses. + */ + continue; + TCNT1 = 0; // reset timer changed = 0; - usb_serial_putchar(val ? '1' : '0'); - LED_OFF; + +// usb_serial_putchar(count > 16667 ? '>' : '<'); + send_int(count); + usb_serial_putchar(' '); + send_int(latency); + usb_serial_putchar('\n'); + latency = TCNT1; + } else if ((val == 1) && (changed == 0)) { + /* leading edge of pulse. + */ + changed = 1; +// usb_serial_putchar('0'); } } } @@ -85,6 +102,23 @@ void send_str(const char *s) } } +/* Write a decimal integer to the serial port + */ +void send_int(int val) +{ + char c_out[10]; + int ptr; + c_out[ptr++] = '\0'; + while (val > 0) { + c_out[ptr++] = (val % 10) + '0'; + val /= 10; + } + ptr--; + while (ptr) { + usb_serial_putchar(c_out[ptr--]); + } +} + // Receive a string from the USB serial port. The string is stored // in the buffer and this function will not exceed the buffer size. // A carriage return or newline completes the string, and is not diff --git a/host/client.c b/host/client.c new file mode 100644 index 0000000..29a2455 --- /dev/null +++ b/host/client.c @@ -0,0 +1,65 @@ +/* Thinger to read 60hz cycle times and display diagnostics in a kind + * of stripcharty way. + */ + +#include <unistd.h> +#include <stdio.h> +#include <fcntl.h> + +#define QUEUE 100 +#define WIDTH 40 + +int main(int *argc, char **argv) +{ + char line[WIDTH + 10]; + double bottom = 1000000/59.9; + double top = 1000000/60.1; + double center = 1000000/60; + double queue[QUEUE]; + int counter; + int qpos = 0; + int fd = open("/dev/ttyACM0", O_RDONLY); + + while (1) { + double current, average; + char line[] = " | "; + char inlin[20]; + int position, pos_avg, i; + int len = read(fd, &inlin, 20); + if (len == 0) { + puts("Fucked\n"); + continue; + } + current = (double)atoi(&inlin); + queue[qpos++] = current; + counter++; + if (qpos == QUEUE) + qpos = 0; + + average = 0; + for (i = 0; i < QUEUE; i++) { + average += queue[i]; + } + average /= QUEUE; + pos_avg = WIDTH-(int)((top-average)/((top-bottom)/WIDTH)); + position = WIDTH-(int)((top-current)/((top-bottom)/WIDTH)); + + if (position > WIDTH) { + line[WIDTH] = '>'; + } else if (position < 0) { + line[0] = '<'; + } else { + line[position] = '.'; + } + + if (pos_avg > WIDTH) { + line[WIDTH] = '_'; + } else if (pos_avg < 0) { + line[0] = '_'; + } else { + line[pos_avg] = '*'; + } + if (counter % 15 == 0) + printf("[%s] %f\n", line, 1/(average/1000000)); + } +} @@ -1,124 +0,0 @@ -/* Keyboard example for Teensy USB Development Board - * http://www.pjrc.com/teensy/usb_keyboard.html - * Copyright (c) 2008 PJRC.COM, LLC - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include <avr/io.h> -#include <avr/pgmspace.h> -#include <avr/interrupt.h> -#include <util/delay.h> -#include "usb_keyboard.h" - -#define LED_CONFIG (DDRD |= (1<<6)) -#define LED_ON (PORTD &= ~(1<<6)) -#define LED_OFF (PORTD |= (1<<6)) -#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) - -uint8_t number_keys[10]= - {KEY_0,KEY_1,KEY_2,KEY_3,KEY_4,KEY_5,KEY_6,KEY_7,KEY_8,KEY_9}; - -uint16_t idle_count=0; - -int main(void) -{ - uint8_t b, d, mask, i, reset_idle; - uint8_t b_prev=0xFF, d_prev=0xFF; - - // set for 16 MHz clock - CPU_PRESCALE(0); - - // Configure all port B and port D pins as inputs with pullup resistors. - // See the "Using I/O Pins" page for details. - // http://www.pjrc.com/teensy/pins.html - DDRD = 0x00; - DDRB = 0x00; - PORTB = 0xFF; - PORTD = 0xFF; - - // Initialize the USB, and then wait for the host to set configuration. - // If the Teensy is powered without a PC connected to the USB port, - // this will wait forever. - usb_init(); - while (!usb_configured()) /* wait */ ; - - // Wait an extra second for the PC's operating system to load drivers - // and do whatever it does to actually be ready for input - _delay_ms(1000); - - // Configure timer 0 to generate a timer overflow interrupt every - // 256*1024 clock cycles, or approx 61 Hz when using 16 MHz clock - // This demonstrates how to use interrupts to implement a simple - // inactivity timeout. - TCCR0A = 0x00; - TCCR0B = 0x05; - TIMSK0 = (1<<TOIE0); - - while (1) { - // read all port B and port D pins - b = PINB; - d = PIND; - // check if any pins are low, but were high previously - mask = 1; - reset_idle = 0; - for (i=0; i<8; i++) { - if (((b & mask) == 0) && (b_prev & mask) != 0) { - usb_keyboard_press(KEY_B, KEY_SHIFT); - usb_keyboard_press(number_keys[i], 0); - reset_idle = 1; - } - if (((d & mask) == 0) && (d_prev & mask) != 0) { - usb_keyboard_press(KEY_D, KEY_SHIFT); - usb_keyboard_press(number_keys[i], 0); - reset_idle = 1; - } - mask = mask << 1; - } - // if any keypresses were detected, reset the idle counter - if (reset_idle) { - // variables shared with interrupt routines must be - // accessed carefully so the interrupt routine doesn't - // try to use the variable in the middle of our access - cli(); - idle_count = 0; - sei(); - } - // now the current pins will be the previous, and - // wait a short delay so we're not highly sensitive - // to mechanical "bounce". - b_prev = b; - d_prev = d; - _delay_ms(2); - } -} - -// This interrupt routine is run approx 61 times per second. -// A very simple inactivity timeout is implemented, where we -// will send a space character. -ISR(TIMER0_OVF_vect) -{ - idle_count++; - if (idle_count > 61 * 8) { - idle_count = 0; - usb_keyboard_press(KEY_SPACE, 0); - } -} - - |
