示例#1
0
文件: mpu6050.c 项目: nnayo/egere
struct mpu6050_t* mpu6050_alloc(struct avr_t * avr, uint8_t addr, struct sc18is600_t* sc18)
{
	struct mpu6050_t* mpu;

    // allocate and reset the object
	mpu = malloc(sizeof(mpu6050_t));
	memset(mpu, 0, sizeof(mpu6050_t));

	mpu->avr = avr;
	mpu->self_addr = addr;

    // create the irqs
	mpu->irq = avr_alloc_irq(&avr->irq_pool, MPU_IRQ_IN, MPU_IRQ_COUNT, mpu_irq_names);
	avr_irq_register_notify(mpu->irq + MPU_IRQ_IN, mpu6050_i2c_in_hook, mpu);

	if (sc18) {
		// connect to the TWI/i2c master of the SC18IS600
		avr_irq_t * sc18_irq = sc18is600_i2c_irq_get(sc18);
		avr_connect_irq(sc18_irq + SC18_I2C_IRQ_OUT, mpu->irq + MPU_IRQ_IN);
		avr_connect_irq(mpu->irq + MPU_IRQ_OUT, sc18_irq + SC18_I2C_IRQ_IN);
	}
	else {
		// "connect" the IRQs of the MPU to the TWI/i2c master of the AVR
		uint32_t i2c_irq_base = AVR_IOCTL_TWI_GETIRQ(0);
		avr_connect_irq(mpu->irq + MPU_IRQ_OUT, avr_io_getirq(avr, i2c_irq_base, TWI_IRQ_INPUT));
		avr_connect_irq(avr_io_getirq(avr, i2c_irq_base, TWI_IRQ_OUTPUT), mpu->irq + MPU_IRQ_IN);
	}

	return mpu;
}
示例#2
0
void
thermistor_init (struct avr_t *avr,
                 thermistor_p p,
                 int adc_mux_number,
                 short *table, int table_entries, int oversampling, float start_temp)
{
  p->avr = avr;
  p->irq = avr_alloc_irq (&avr->irq_pool, 0, IRQ_TERM_COUNT, irq_names);
  avr_irq_register_notify (p->irq + IRQ_TERM_ADC_TRIGGER_IN, thermistor_in_hook, p);
  avr_irq_register_notify (p->irq + IRQ_TERM_TEMP_VALUE_IN, thermistor_value_in_hook, p);

  p->oversampling = oversampling;
  p->table = table;
  p->table_entries = table_entries;
  p->adc_mux_number = adc_mux_number;
  p->current = start_temp;

  avr_irq_t *src = avr_io_getirq (p->avr, AVR_IOCTL_ADC_GETIRQ, ADC_IRQ_OUT_TRIGGER);
  avr_irq_t *dst = avr_io_getirq (p->avr, AVR_IOCTL_ADC_GETIRQ, adc_mux_number);
  if (src && dst)
    {
      avr_connect_irq (src, p->irq + IRQ_TERM_ADC_TRIGGER_IN);
      avr_connect_irq (p->irq + IRQ_TERM_ADC_VALUE_OUT, dst);
    }

  printf ("%s on ADC %d start %.2f\n", __func__, adc_mux_number, p->current);
}
示例#3
0
void LcdLogic::wireHook(avr_t *avr)
{
    this->avr = avr;

    hd44780_init(avr, &hd44780, WIDTH, HEIGHT, this, LcdLogic::displayChanged);

    /* Connect data lines to Port C, 4-7 (bidirectional). */
    for (int i = 0; i < 4; i++) {
        avr_irq_t * iavr = avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 4 + i);
        avr_irq_t * ilcd = hd44780.irq + IRQ_HD44780_D4 + i;
        // AVR -> LCD
        avr_connect_irq(iavr, ilcd);
        // LCD -> AVR
        avr_connect_irq(ilcd, iavr);
    }

    avr_connect_irq(avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 2),
                    hd44780.irq + IRQ_HD44780_RS);
    avr_connect_irq(avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 3),
                    hd44780.irq + IRQ_HD44780_E);
    /* RW is set to GND. */

    avr_vcd_init(avr, "lcd.vcd", &vcdFile, 100000);
    avr_vcd_add_signal(&vcdFile,
            avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), IOPORT_IRQ_PIN_ALL),
            4 /* bits */, "D4-D7");
    avr_vcd_add_signal(&vcdFile,
            avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 2),
            1 /* bits */, "RS");
    avr_vcd_add_signal(&vcdFile,
            avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 3),
            1 /* bits */, "E");
}
示例#4
0
static void
_avr_io_command_write (struct avr_t *avr, avr_io_addr_t addr, uint8_t v, void *param)
{
  AVR_LOG (avr, LOG_TRACE, "%s %02x\n", __FUNCTION__, v);
  switch (v)
    {
    case SIMAVR_CMD_VCD_START_TRACE:
      if (avr->vcd)
        avr_vcd_start (avr->vcd);
      break;
      
    case SIMAVR_CMD_VCD_STOP_TRACE:
      if (avr->vcd)
        avr_vcd_stop (avr->vcd);
      break;
      
    case SIMAVR_CMD_UART_LOOPBACK:
      {
        avr_irq_t *src = avr_io_getirq (avr, AVR_IOCTL_UART_GETIRQ ('0'), UART_IRQ_OUTPUT);
        avr_irq_t *dst = avr_io_getirq (avr, AVR_IOCTL_UART_GETIRQ ('0'), UART_IRQ_INPUT);
        if (src && dst)
          {
            AVR_LOG (avr, LOG_TRACE, "%s activating uart local echo IRQ src %p dst %p\n",
                     __FUNCTION__, src, dst);
            avr_connect_irq (src, dst);
          }
      }
      break;
    }
}
示例#5
0
void uart_udp_connect(uart_udp_t * p, char uart)
{
	// disable the stdio dump, as we are sending binary there
	uint32_t f = 0;
	avr_ioctl(p->avr, AVR_IOCTL_UART_GET_FLAGS(uart), &f);
	f &= ~AVR_UART_FLAG_STDIO;
	avr_ioctl(p->avr, AVR_IOCTL_UART_SET_FLAGS(uart), &f);

	avr_irq_t * src = avr_io_getirq(p->avr, AVR_IOCTL_UART_GETIRQ(uart), UART_IRQ_OUTPUT);
	avr_irq_t * dst = avr_io_getirq(p->avr, AVR_IOCTL_UART_GETIRQ(uart), UART_IRQ_INPUT);
	avr_irq_t * xon = avr_io_getirq(p->avr, AVR_IOCTL_UART_GETIRQ(uart), UART_IRQ_OUT_XON);
	avr_irq_t * xoff = avr_io_getirq(p->avr, AVR_IOCTL_UART_GETIRQ(uart), UART_IRQ_OUT_XOFF);
	if (src && dst) {
		avr_connect_irq(src, p->irq + IRQ_UART_UDP_BYTE_IN);
		avr_connect_irq(p->irq + IRQ_UART_UDP_BYTE_OUT, dst);
	}
	if (xon)
		avr_irq_register_notify(xon, uart_udp_xon_hook, p);
	if (xoff)
		avr_irq_register_notify(xoff, uart_udp_xoff_hook, p);
}
示例#6
0
void LedButtonsLogic::wireHook(avr_t *avr)
{
    this->avr = avr;

    /* Every port has 8 pins. */
    const int count = strlen(ports) * 8;

    /* Construct the port names. */
    int nameLength = sizeof("PORTA0");
    const char *names[count];
    char _names[count * nameLength];
    char *s = _names;
    for (int i = 0; i < count; i++) {
        int port = i / 8;
        int pin = i % 8;

        snprintf(s, nameLength, "PORT%c%d", ports[port], pin);
        names[i] = s;
        s += nameLength;
    }

    irq = avr_alloc_irq(&avr->irq_pool, 0, count, names);

    for (int i = 0; i < count; i++) {
        int port = i / 8;
        int pin = i % 8;

        avr_connect_irq(irq + i, avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ(ports[port]), pin));

        /* We need this helper struct to keep track of 1) which port the IRQ came from,
         * and 2) which class instance to notify. */
        CallbackData *d = new CallbackData;
        d->instance = this;
        d->port = 'A' + port;
        callbackData.append(d);

        avr_irq_register_notify(avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ(ports[port]), pin),
                                LedButtonsLogic::pinChanged, d);
    }

    avr_vcd_init(avr, "ledbuttons.vcd", &vcdFile, 100000);
    for (int i = 0; i < 8; i++) {
        char name[6];
        snprintf(name, 6, "PORT%c", ports[i]);
        avr_vcd_add_signal(&vcdFile,
                avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ(ports[i]), IOPORT_IRQ_PIN_ALL),
                           8 /* bits */, name);
    }
}
示例#7
0
static void avr_extint_reset(avr_io_t * port)
{
	avr_extint_t * p = (avr_extint_t *)port;

	for (int i = 0; i < EXTINT_COUNT; i++) {
		avr_irq_register_notify(p->io.irq + i, avr_extint_irq_notify, p);

		if (p->eint[i].port_ioctl) {
			avr_irq_t * irq = avr_io_getirq(p->io.avr,
					p->eint[i].port_ioctl, p->eint[i].port_pin);

			avr_connect_irq(irq, p->io.irq + i);
		}
	}
}
示例#8
0
文件: simul.c 项目: fvicente/binw2
int main(int argc, char *argv[])
{
	elf_firmware_t		f;
	const char			*fname="../src/binw2.elf";
	const char			*mmcu="attiny13";

	elf_read_firmware(fname, &f);

	snprintf(f.mmcu, sizeof(f.mmcu) - 1, "%s", mmcu);
	f.frequency = 4800000;
	printf("firmware %s f=%d mmcu=%s\n", fname, (int)f.frequency, f.mmcu);

	avr = avr_make_mcu_by_name(f.mmcu);
	if (!avr) {
		fprintf(stderr, "%s: AVR '%s' not known\n", argv[0], f.mmcu);
		exit(1);
	}
	avr_init(avr);
	avr_load_firmware(avr, &f);

	// initialize our 'peripheral'
	button_init(avr, &button, "button");

	// "connect" the output irq of the button to the port pin of the AVR
	avr_connect_irq(
		button.irq + IRQ_BUTTON_OUT,
		avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), IOPORT_IRQ_PIN4));

	avr_irq_register_notify(
		avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), IOPORT_IRQ_DIRECTION_ALL),
		ddr_hook,
		NULL);

	avr_irq_register_notify(
		avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), IOPORT_IRQ_PIN_ALL),
		pin_changed_hook, 
		"portb");

	// even if not setup at startup, activate gdb if crashing
	avr->gdb_port = 1234;
	//if (0) {
	//	//avr->state = cpu_Stopped;
	//	avr_gdb_init(avr);
	//}

	/*
	 *	VCD file initialization
	 *	
	 *	This will allow you to create a "wave" file and display it in gtkwave
	 *	Pressing "r" and "s" during the demo will start and stop recording
	 *	the pin changes
	 */
	avr_vcd_init(avr, "gtkwave_output.vcd", &vcd_file, 100000 /* usec */);
	avr_vcd_add_signal(&vcd_file, 
		avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), IOPORT_IRQ_PIN_ALL), 8 /* bits */ ,
		"portb" );
	avr_vcd_add_signal(&vcd_file, 
		button.irq + IRQ_BUTTON_OUT, 1 /* bits */ ,
		"button" );

	// 'raise' it, it's a "pullup"
	avr_raise_irq(button.irq + IRQ_BUTTON_OUT, 0);

	printf( "Launching binw2 simulation\n"
			"   Press 'space' to press virtual button attached to pin %d\n"
			"   Press 'q' to quit\n"
			"   Press 'r' to start recording a 'wave' file\n"
			"   Press 's' to stop recording\n",
			IOPORT_IRQ_PIN4);

	/*
	 * OpenGL init, can be ignored
	 */
	glutInit(&argc, argv);		/* initialize GLUT system */

	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
	glutInitWindowSize(5 * SZ_PIXSIZE, 7 * SZ_PIXSIZE);
	window = glutCreateWindow("Glut");	/* create window */

	// Set up projection matrix
	glMatrixMode(GL_PROJECTION); // Select projection matrix
	glLoadIdentity(); // Start with an identity matrix
	glOrtho(0, 5 * SZ_PIXSIZE, 0, 7 * SZ_PIXSIZE, 0, 10);
	//glScalef(1, -1, 1);
	//glTranslatef(0, -7 * SZ_PIXSIZE, 0);

	glutDisplayFunc(displayCB);		/* set window's display callback */
	glutKeyboardFunc(keyCB);		/* set window's key callback */
	glutTimerFunc(1000 / 24, timerCB, 0);

	// the AVR run on it's own thread. it even allows for debugging!
	pthread_t run;
	pthread_create(&run, NULL, avr_run_thread, NULL);

	glutMainLoop();
}
示例#9
0
static void avr_timer_reset(avr_io_t * port)
{
	avr_timer_t * p = (avr_timer_t *)port;
	avr_cycle_timer_cancel(p->io.avr, avr_timer_tov, p);
	avr_cycle_timer_cancel(p->io.avr, avr_timer_compa, p);
	avr_cycle_timer_cancel(p->io.avr, avr_timer_compb, p);
	avr_cycle_timer_cancel(p->io.avr, avr_timer_compc, p);

	// check to see if the comparators have a pin output. If they do,
	// (try) to get the ioport corresponding IRQ and connect them
	// they will automagically be triggered when the comparator raises
	// it's own IRQ
	for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) {
		p->comp[compi].comp_cycles = 0;

		avr_ioport_getirq_t req = {
			.bit = p->comp[compi].com_pin
		};
		if (avr_ioctl(port->avr, AVR_IOCTL_IOPORT_GETIRQ_REGBIT, &req) > 0) {
			// cool, got an IRQ
//			printf("%s-%c COMP%c Connecting PIN IRQ %d\n", __FUNCTION__, p->name, 'A'+compi, req.irq[0]->irq);
			avr_connect_irq(&port->irq[TIMER_IRQ_OUT_COMP + compi], req.irq[0]);
		}
	}
	avr_ioport_getirq_t req = {
		.bit = p->icp
	};
	if (avr_ioctl(port->avr, AVR_IOCTL_IOPORT_GETIRQ_REGBIT, &req) > 0) {
		// cool, got an IRQ for the input capture pin
//		printf("%s-%c ICP Connecting PIN IRQ %d\n", __FUNCTION__, p->name, req.irq[0]->irq);
		avr_irq_register_notify(req.irq[0], avr_timer_irq_icp, p);
	}

}

static const char * irq_names[TIMER_IRQ_COUNT] = {
	[TIMER_IRQ_OUT_PWM0] = "8>pwm0",
	[TIMER_IRQ_OUT_PWM1] = "8>pwm1",
	[TIMER_IRQ_OUT_COMP + 0] = ">compa",
	[TIMER_IRQ_OUT_COMP + 1] = ">compb",
	[TIMER_IRQ_OUT_COMP + 2] = ">compc",
};

static	avr_io_t	_io = {
	.kind = "timer",
	.reset = avr_timer_reset,
	.irq_names = irq_names,
};

void avr_timer_init(avr_t * avr, avr_timer_t * p)
{
	p->io = _io;

	avr_register_io(avr, &p->io);
	avr_register_vector(avr, &p->overflow);
	avr_register_vector(avr, &p->icr);

	// allocate this module's IRQ
	avr_io_setirqs(&p->io, AVR_IOCTL_TIMER_GETIRQ(p->name), TIMER_IRQ_COUNT, NULL);

	// marking IRQs as "filtered" means they don't propagate if the
	// new value raised is the same as the last one.. in the case of the
	// pwm value it makes sense not to bother.
	p->io.irq[TIMER_IRQ_OUT_PWM0].flags |= IRQ_FLAG_FILTERED;
	p->io.irq[TIMER_IRQ_OUT_PWM1].flags |= IRQ_FLAG_FILTERED;

	if (p->wgm[0].reg) // these are not present on older AVRs
		avr_register_io_write(avr, p->wgm[0].reg, avr_timer_write, p);
	avr_register_io_write(avr, p->cs[0].reg, avr_timer_write, p);

	// this assumes all the "pending" interrupt bits are in the same
	// register. Might not be true on all devices ?
	avr_register_io_write(avr, p->overflow.raised.reg, avr_timer_write_pending, p);

	/*
	 * Even if the timer is 16 bits, we don't care to have watches on the
	 * high bytes because the datasheet says that the low address is always
	 * the trigger.
	 */
	for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) {
		avr_register_vector(avr, &p->comp[compi].interrupt);

		if (p->comp[compi].r_ocr) // not all timers have all comparators
			avr_register_io_write(avr, p->comp[compi].r_ocr, avr_timer_write_ocr, p);
	}
	avr_register_io_write(avr, p->r_tcnt, avr_timer_tcnt_write, p);
	avr_register_io_read(avr, p->r_tcnt, avr_timer_tcnt_read, p);
}
示例#10
0
int main(int argc, char *argv[])
{
	elf_firmware_t f;
	//const char * fname =  "atmega48_ledramp.axf";
	const char * fname =  argv[1];
	char path[256];

//	sprintf(path, "%s/%s", dirname(argv[0]), fname);
//	printf("Firmware pathname is %s\n", path);
	elf_read_firmware(fname, &f);

	printf("firmware %s f=%d mmcu=%s\n", fname, (int)f.frequency, f.mmcu);

	avr = avr_make_mcu_by_name(f.mmcu);
	if (!avr) {
		fprintf(stderr, "%s: AVR '%s' now known\n", argv[0], f.mmcu);
		exit(1);
	}
	avr_init(avr);
	avr_load_firmware(avr, &f);

	// initialize our 'peripheral'
	button_init(avr, &button, "button");
	// "connect" the output irw of the button to the port pin of the AVR
	avr_connect_irq(
		button.irq + IRQ_BUTTON_OUT,
		avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 0));

	// connect all the pins on port B to our callback
	for (int i = 0; i < 8; i++)
		avr_irq_register_notify(
			avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), i),
			pin_changed_hook, 
			NULL);

	// even if not setup at startup, activate gdb if crashing
	avr->gdb_port = 1234;
	if (0) {
		//avr->state = cpu_Stopped;
		avr_gdb_init(avr);
	}

	/*
	 *	VCD file initialization
	 *	
	 *	This will allow you to create a "wave" file and display it in gtkwave
	 *	Pressing "r" and "s" during the demo will start and stop recording
	 *	the pin changes
	 */
	avr_vcd_init(avr, "gtkwave_output.vcd", &vcd_file, 100000 /* usec */);
	avr_vcd_add_signal(&vcd_file, 
		avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), IOPORT_IRQ_PIN_ALL), 8 /* bits */ ,
		"portb" );
	avr_vcd_add_signal(&vcd_file, avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), IOPORT_IRQ_PIN0), 1, "portc");
	avr_vcd_add_signal(&vcd_file, 
		button.irq + IRQ_BUTTON_OUT, 1 /* bits */ ,
		"button" );

	// 'raise' it, it's a "pullup"
	avr_raise_irq(button.irq + IRQ_BUTTON_OUT, 1);

	printf( "Demo launching: 'LED' bar is PORTB, updated every 1/64s by the AVR\n"
			"   firmware using a timer. If you press 'space' this presses a virtual\n"
			"   'button' that is hooked to the virtual PORTC pin 0 and will\n"
			"   trigger a 'pin change interrupt' in the AVR core, and will 'invert'\n"
			"   the display.\n"
			"   Press 'q' to quit\n\n"
			"   Press 'r' to start recording a 'wave' file\n"
			"   Press 's' to stop recording\n"
			);

	/*
	 * OpenGL init, can be ignored
	 */
	glutInit(&argc, argv);		/* initialize GLUT system */

	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
	glutInitWindowSize(8 * pixsize, 1 * pixsize);		/* width=400pixels height=500pixels */
	window = glutCreateWindow("Glut");	/* create window */

	// Set up projection matrix
	glMatrixMode(GL_PROJECTION); // Select projection matrix
	glLoadIdentity(); // Start with an identity matrix
	glOrtho(0, 8 * pixsize, 0, 1 * pixsize, 0, 10);
	glScalef(1,-1,1);
	glTranslatef(0, -1 * pixsize, 0);

	glutDisplayFunc(displayCB);		/* set window's display callback */
	glutKeyboardFunc(keyCB);		/* set window's key callback */
	glutTimerFunc(1000 / 24, timerCB, 0);

	// the AVR run on it's own thread. it even allows for debugging!
	pthread_t run;
	pthread_create(&run, NULL, avr_run_thread, NULL);

	glutMainLoop();
}
示例#11
0
文件: main.c 项目: 33d/gbsim
int main(int argc, char* argv[]) {
	int r = 0;

	char* elf_file = NULL;
	int gdb_port = 0;

	for (char** arg = &argv[1]; *arg != NULL; ++arg) {
		if (strcmp("-d", *arg) == 0)
			gdb_port = atoi(*(++arg));
		else
			elf_file = *arg;
	}
	if (elf_file == NULL) {
		fprintf(stderr, "Give me a .elf file to load\n");
		return 1;
	}

	elf_firmware_t f;
	elf_read_firmware(elf_file, &f);
	avr_t* avr = avr_make_mcu_by_name("atmega328p");
	if (!avr) {
		fprintf(stderr, "Unsupported cpu atmega328p\n");
		return 1;
	}

	avr_init(avr);
	if (gdb_port != 0) {
		avr->gdb_port = gdb_port;
		avr_gdb_init(avr);
	}
	avr->frequency = 16000000;
	avr_load_firmware(avr, &f);

	pcd8544_init(avr, &lcd);
	avr_connect_irq(avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 2),
			lcd.irq + IRQ_PCD8544_DC);
	avr_connect_irq(avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 1),
			lcd.irq + IRQ_PCD8544_CS);
	avr_connect_irq(avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 0),
			lcd.irq + IRQ_PCD8544_RST);
	avr_connect_irq(avr_io_getirq(avr, AVR_IOCTL_SPI_GETIRQ(0), SPI_IRQ_OUTPUT),
			lcd.irq + IRQ_PCD8544_SPI_IN);

	gb_keypad_init(avr, &keypad);
	for (int i = 0; i < keydefs_length; i++) {
		const keydef_t *k = keydefs + i;
		avr_connect_irq(keypad.irq + k->keypad_key,
				avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ(k->port), k->pin));

		// Start with the pin high
		avr_ioport_t* port = (avr_ioport_t*) avr->io[k->avr_port].w.param;
		key_io[i].pin_mask = (1<<k->pin);
		key_io[i].pull_value = &port->external.pull_value;
		port->external.pull_mask |= key_io[i].pin_mask;
		port->external.pull_value |= key_io[i].pin_mask;
		gb_keypad_press(&keypad, k->keypad_key, 1);
	}

	if (display_init()) {
		lcd_ram_mutex = SDL_CreateMutex();
		SDL_Thread* avr_thread = SDL_CreateThread(avr_run_thread, "avr-thread", avr);
		main_loop();
		SDL_LockMutex(lcd_ram_mutex);
		quit_flag = 1;
		SDL_UnlockMutex(lcd_ram_mutex);
		int avr_thread_return;
		SDL_WaitThread(avr_thread, &avr_thread_return);
		SDL_DestroyMutex(lcd_ram_mutex);
	} else {
		r = 1;
		fprintf(stderr, "%s\n", display_error_message());
	}

	display_destroy();

	return r;
}
示例#12
0
int main(int argc, char *argv[])
{
	elf_firmware_t f;
	const char * fname =  "atmega168_timer_64led.axf";
	//char path[256];

//	sprintf(path, "%s/%s", dirname(argv[0]), fname);
	//printf("Firmware pathname is %s\n", path);
	elf_read_firmware(fname, &f);

	printf("firmware %s f=%d mmcu=%s\n", fname, (int)f.frequency, f.mmcu);

	avr = avr_make_mcu_by_name(f.mmcu);
	if (!avr) {
		fprintf(stderr, "%s: AVR '%s' now known\n", argv[0], f.mmcu);
		exit(1);
	}
	avr_init(avr);
	avr_load_firmware(avr, &f);

	//
	// initialize our 'peripherals'
	//
	hc595_init(avr, &shifter);
	
	button_init(avr, &button[B_START], "button.start");
	avr_connect_irq(
		button[B_START].irq + IRQ_BUTTON_OUT,
		avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('C'), 0));
	button_init(avr, &button[B_STOP], "button.stop");
	avr_connect_irq(
		button[B_STOP].irq + IRQ_BUTTON_OUT,
		avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 1));
	button_init(avr, &button[B_RESET], "button.reset");
	avr_connect_irq(
		button[B_RESET].irq + IRQ_BUTTON_OUT,
		avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 0));

	// connects the fake 74HC595 array to the pins
	avr_irq_t * i_mosi = avr_io_getirq(avr, AVR_IOCTL_SPI_GETIRQ(0), SPI_IRQ_OUTPUT),
			* i_reset = avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('D'), 4),
			* i_latch = avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('D'), 7);
	avr_connect_irq(i_mosi, shifter.irq + IRQ_HC595_SPI_BYTE_IN);
	avr_connect_irq(i_reset, shifter.irq + IRQ_HC595_IN_RESET);
	avr_connect_irq(i_latch, shifter.irq + IRQ_HC595_IN_LATCH);

	avr_irq_t * i_pwm = avr_io_getirq(avr, AVR_IOCTL_TIMER_GETIRQ('0'), TIMER_IRQ_OUT_PWM0);
	avr_irq_register_notify(
		i_pwm,
		pwm_changed_hook, 
		NULL);	
	avr_irq_register_notify(
		shifter.irq + IRQ_HC595_OUT,
		hc595_changed_hook, 
		NULL);

	// even if not setup at startup, activate gdb if crashing
	avr->gdb_port = 1234;
	if (0) {
		//avr->state = cpu_Stopped;
		avr_gdb_init(avr);
	}

	/*
	 *	VCD file initialization
	 *	
	 *	This will allow you to create a "wave" file and display it in gtkwave
	 *	Pressing "r" and "s" during the demo will start and stop recording
	 *	the pin changes
	 */
	avr_vcd_init(avr, "gtkwave_output.vcd", &vcd_file, 10000 /* usec */);

	avr_vcd_add_signal(&vcd_file, 
		avr_get_interrupt_irq(avr, 7), 1 /* bit */ ,
		"TIMER2_COMPA" );
	avr_vcd_add_signal(&vcd_file, 
		avr_get_interrupt_irq(avr, 17), 1 /* bit */ ,
		"SPI_INT" );
	avr_vcd_add_signal(&vcd_file, 
		i_mosi, 8 /* bits */ ,
		"MOSI" );

	avr_vcd_add_signal(&vcd_file, 
		i_reset, 1 /* bit */ ,
		"595_RESET" );
	avr_vcd_add_signal(&vcd_file, 
		i_latch, 1 /* bit */ ,
		"595_LATCH" );
	avr_vcd_add_signal(&vcd_file, 
		button[B_START].irq + IRQ_BUTTON_OUT, 1 /* bits */ ,
		"start" );
	avr_vcd_add_signal(&vcd_file, 
		button[B_STOP].irq + IRQ_BUTTON_OUT, 1 /* bits */ ,
		"stop" );
	avr_vcd_add_signal(&vcd_file, 
		button[B_RESET].irq + IRQ_BUTTON_OUT, 1 /* bits */ ,
		"reset" );

	avr_vcd_add_signal(&vcd_file, 
		shifter.irq + IRQ_HC595_OUT, 32 /* bits */ ,
		"HC595" );
	avr_vcd_add_signal(&vcd_file, 
		i_pwm, 8 /* bits */ ,
		"PWM" );

	// 'raise' it, it's a "pullup"
	avr_raise_irq(button[B_START].irq + IRQ_BUTTON_OUT, 1);
	avr_raise_irq(button[B_STOP].irq + IRQ_BUTTON_OUT, 1);
	avr_raise_irq(button[B_RESET].irq + IRQ_BUTTON_OUT, 1);

	printf( "Demo : This is a real world firmware, a 'stopwatch'\n"
			"   timer that can count up to 99 days. It features a PWM control of the\n"
			"   brightness, blinks the dots, displays the number of days spent and so on.\n\n"
			"   Press '0' to press the 'start' button\n"
			"   Press '1' to press the 'stop' button\n"
			"   Press '2' to press the 'reset' button\n"
			"   Press 'q' to quit\n\n"
			"   Press 'r' to start recording a 'wave' file - with a LOT of data\n"
			"   Press 's' to stop recording\n"
			"  + Make sure to watch the brightness dim once you stop the timer\n\n"
			);

	/*
	 * OpenGL init, can be ignored
	 */
	glutInit(&argc, argv);		/* initialize GLUT system */


	int w = 22, h = 8;
	
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
	glutInitWindowSize(w * pixsize, h * pixsize);		/* width=400pixels height=500pixels */
	window = glutCreateWindow("Press 0, 1, 2 or q");	/* create window */

	// Set up projection matrix
	glMatrixMode(GL_PROJECTION); // Select projection matrix
	glLoadIdentity(); // Start with an identity matrix
	glOrtho(0, w * pixsize, 0, h * pixsize, 0, 10);
	glScalef(1,-1,1);
	glTranslatef(0, -1 * h * pixsize, 0);

	glutDisplayFunc(displayCB);		/* set window's display callback */
	glutKeyboardFunc(keyCB);		/* set window's key callback */
	glutTimerFunc(1000 / 24, timerCB, 0);

	// the AVR run on it's own thread. it even allows for debugging!
	pthread_t run;
	pthread_create(&run, NULL, avr_run_thread, NULL);

	glutMainLoop();
}