static void timer_default_config(timer_dev *dev) { timer_adv_reg_map *regs = (dev->regs).adv; const uint16 full_overflow = 0xFFFF; const uint16 half_duty = 0x8FFF; timer_init(dev); timer_pause(dev); regs->CR1 = TIMER_CR1_ARPE; regs->PSC = 1; regs->SR = 0; regs->DIER = 0; regs->EGR = TIMER_EGR_UG; switch (dev->type) { case TIMER_ADVANCED: regs->BDTR = TIMER_BDTR_MOE | TIMER_BDTR_LOCK_OFF; // fall-through case TIMER_GENERAL: timer_set_reload(dev, full_overflow); for (uint8 channel = 1; channel <= 4; channel++) { if (timer_has_cc_channel(dev, channel)) { timer_set_compare(dev, channel, half_duty); timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1, TIMER_OC_PE); } } // fall-through case TIMER_BASIC: break; } timer_generate_update(dev); timer_resume(dev); }
void espos_test_run_in_isr(espos_test_isr_routine routine) { int timer_group = TIMER_GROUP_0; int timer_idx = TIMER_0; timer_config_t config; config.alarm_en = 1; config.auto_reload = 0; config.counter_dir = TIMER_COUNT_UP; config.divider = TIMER_DIVIDER; config.intr_type = TIMER_INTR_SEL; config.counter_en = TIMER_PAUSE; /*Configure timer*/ timer_init(timer_group, timer_idx, &config); /*Stop timer counter*/ timer_pause(timer_group, timer_idx); /*Load counter value */ timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL); /*Set alarm value*/ timer_set_alarm_value(timer_group, timer_idx, 1); timer_set_auto_reload(timer_group, timer_idx, TIMER_AUTORELOAD_DIS); /*Enable timer interrupt*/ timer_enable_intr(timer_group, timer_idx); /*Set ISR handler*/ timer_isr_register(timer_group, timer_idx, timer_isr, (void *) routine, ESP_INTR_FLAG_IRAM, NULL); /*Start timer counter*/ timer_start(timer_group, timer_idx); }
// --------- Do not submit the following functions --------- // void simple_timer() { Game game; setup_score(&game); while (!game.over) { if (update_score(&game)) { clear_screen(); display_score(&game); show_screen(); } timer_pause(100); } timer_pause(1500); }
void TIM2_init() { uint32_t SystemCoreClock = 72000000; uint16_t prescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1; rcc_clk_enable(RCC_TIMER2); /* Time base configuration */ timer_pause(TIMER2); timer_set_prescaler(TIMER2, prescalerValue); timer_set_reload(TIMER2, 29); // 800kHz /* Timing Mode configuration: Channel 1 */ timer_set_mode(TIMER2, 1, TIMER_OUTPUT_COMPARE); timer_set_compare(TIMER2, 1, 8); timer_oc_set_mode(TIMER2, 1, TIMER_OC_MODE_FROZEN, ~TIMER_OC_PE); /* Timing Mode configuration: Channel 2 */ timer_set_mode(TIMER2, 2, TIMER_OUTPUT_COMPARE); timer_set_compare(TIMER2, 2, 17); timer_oc_set_mode(TIMER2, 2, TIMER_OC_MODE_PWM_1, ~TIMER_OC_PE); //timer_resume(TIMER2); timer_attach_interrupt(TIMER2, TIMER_UPDATE_INTERRUPT, TIM2_IRQHandler); /* configure TIM2 interrupt */ nvic_irq_set_priority(NVIC_TIMER2, 2); nvic_irq_enable(NVIC_TIMER2); }
void Dynamixel::begin(int baud) { //TxDString("[DXL]start begin\r\n"); afio_remap(AFIO_REMAP_USART1);//USART1 -> DXL afio_cfg_debug_ports(AFIO_DEBUG_FULL_SWJ_NO_NJRST); #ifdef BOARD_CM900 //Engineering version case gpio_set_mode(PORT_ENABLE_TXD, PIN_ENABLE_TXD, GPIO_OUTPUT_PP); gpio_set_mode(PORT_ENABLE_RXD, PIN_ENABLE_RXD, GPIO_OUTPUT_PP); gpio_write_bit(PORT_ENABLE_TXD, PIN_ENABLE_TXD, 0 );// TX Disable gpio_write_bit(PORT_ENABLE_RXD, PIN_ENABLE_RXD, 1 );// RX Enable #else gpio_set_mode(PORT_TXRX_DIRECTION, PIN_TXRX_DIRECTION, GPIO_OUTPUT_PP); gpio_write_bit(PORT_TXRX_DIRECTION, PIN_TXRX_DIRECTION, 0 );// RX Enable #endif timer_set_mode(TIMER2, TIMER_CH1, TIMER_OUTPUT_COMPARE); timer_pause(TIMER2); uint16 ovf = timer_get_reload(TIMER2); timer_set_count(TIMER2, min(0, ovf)); timer_set_reload(TIMER2, 30000);//set overflow ovf = timer_get_reload(TIMER2); timer_set_compare(TIMER2, TIMER_CH1, min(1000, ovf)); timer_attach_interrupt(TIMER2, TIMER_CH1, TIM2_IRQHandler); timer_generate_update(TIMER2); timer_resume(TIMER2); dxl_initialize(0, baud); }
bool Servo::attach(uint8 pin, uint16 minPW, uint16 maxPW, int16 minAngle, int16 maxAngle) { timer_dev *tdev = PIN_MAP[pin].timer_device; if (tdev == NULL) { // don't reset any fields or ASSERT(0), to keep driving any // previously attach()ed servo. return false; } if (this->attached()) { this->detach(); } this->pin = pin; this->minPW = minPW; this->maxPW = maxPW; this->minAngle = minAngle; this->maxAngle = maxAngle; pinMode(pin, PWM); timer_pause(tdev); timer_set_prescaler(tdev, SERVO_PRESCALER - 1); // prescaler is 1-based timer_set_reload(tdev, SERVO_OVERFLOW); timer_generate_update(tdev); timer_resume(tdev); return true; }
/** * Non-blocking piezo/headphone beep */ void buzzer_nonblocking_buzz(float time, bool piezo, bool headphones) { // No need to go further if both outputs are // false if (!(piezo || headphones)) return; piezo_out = piezo; headphones_out = headphones; buzz_time = 4100*time*2; // Configure timer2 to fire every N microseconds timer_pause(TIMER2); timer_set_prescaler(TIMER2,1); timer_set_reload(TIMER2,(125*CYCLES_PER_MICROSECOND)/2); // setup interrupt on channel 2 timer_set_mode(TIMER2,TIMER_CH2,TIMER_OUTPUT_COMPARE); timer_set_compare(TIMER2,TIMER_CH2,MAX_RELOAD-1); timer_attach_interrupt(TIMER2,TIMER_CH2,buzzer_handler); // start timer2 buzz_count=0; timer_generate_update(TIMER2); // refresh timer count, prescale, overflow timer_resume(TIMER2); }
/* TIM2 Interrupt Handler gets executed on every TIM2 Update if enabled */ void TIM2_IRQHandler(void) { // Clear TIM2 Interrupt Flag TIMER2->regs.gen->SR &= ~TIMER_SR_UIF; /* check if certain number of overflows has occured yet * this ISR is used to guarantee a 50us dead time on the data lines * before another frame is transmitted */ if (TIM2_overflows < (uint8_t)WS2812_DEADPERIOD) { // count the number of occured overflows TIM2_overflows++; } else { // clear the number of overflows TIM2_overflows = 0; // stop TIM2 now because dead period has been reached timer_pause(TIMER2); /* disable the TIM2 Update interrupt again * so it doesn't occur while transmitting data */ timer_disable_irq(TIMER2, TIMER_UPDATE_INTERRUPT); // finally indicate that the data frame has been transmitted WS2812_TC = 1; } }
void buzzer_handler(void) { gpio_toggle_bit(PIN_MAP[BUZZER_PWM].gpio_device, PIN_MAP[BUZZER_PWM].gpio_bit); buzz_count++; if(buzz_count == buzz_time) { timer_pause(TIMER2); } }
double timer_stop(struct timer_state* timer) { timer_pause(timer); double duration = timer->duration; timer_reset(timer); return duration; }
int main(int argc, char *argv[]) { sigjmp_buf env; int var=1, i, s; sTimer timers[]={ {20, sighnd, (void *)1, &env, 20}, {15, sighnd, (void *)2, &env, 15}, {13, sighnd, (void *)3, &env, 13}, {10, sighnd, (void *)4, &env, 10}, { 9, sighnd, (void *)5, &env, 9}, { 5, sighnd, (void *)6, &env, 5}, { 1, sighnd, (void *)7, &env, 1} }; printf("\x1b[2J\x1b[0;0H"); for(i=0; i<sizeof(timers)/sizeof(*timers); i++) { if(i!=4) timer_start(&timers[i], 0); printf("%2d:\n", timers[i].jmpcode); } printf("\n"); s=sigsetjmp(env, 1); if(s==0) var=2; else printf("Timer %d expired\n", s); if(s==5) { timer_pause(&timers[1]); printf("Paused timer 15\n"); timer_start(&timers[4], 0); printf("Started timer 9\n"); timer_stop(&timers[2]); printf("Stopped timer 13\n"); } if(s==9) { timer_start(&timers[2], 13); printf("Started timer 13\n"); } if(s==10) { timer_resume(&timers[1]); printf("Resumed timer 15\n"); } getchar(); printf("var=%d\n", var); return 0; }
int main( void ) { setup_screen(); srand( time( NULL ) ); demo(); timer_pause( 5000 ); cleanup_screen(); return 0; }
static gboolean read_stdin(GIOChannel *source, GIOCondition condition, gpointer data) { /* Unused. */ (void)source; (void)condition; GString *buffer = g_string_new(""); GError *err = NULL; gchar **tokens = NULL; gchar *line_copy = NULL; gint num_tokens = 0; struct application_info *app = (struct application_info *)data; /* Mixing stdio.h and GIO is probably a bad idea, thus we better use * GIO here to read from stdin. */ if (g_io_channel_read_line_string(app->gio.stdin_channel, buffer, NULL, &err) == G_IO_STATUS_NORMAL) { /* Copy string from GString into a gchar so we can use * g_strchomp() on it. */ line_copy = g_strdup(buffer->str); g_string_free(buffer, TRUE); tokens = g_strsplit(g_strchomp(line_copy), " ", -1); for (num_tokens = 0; tokens[num_tokens] != NULL; num_tokens++) /* No body, just count the tokens. */ ; if (num_tokens >= 1) { if (g_strcmp0(tokens[0], "start") == 0) { timer_start(app); } else if (g_strcmp0(tokens[0], "pause") == 0) { timer_pause(app); } else if (g_strcmp0(tokens[0], "reset") == 0) { timer_reset(app); } } g_strfreev(tokens); g_free(line_copy); } if (err != NULL) { g_error_free(err); } /* Do not remove this watch. */ return TRUE; }
static void esp_apptrace_dummy_task(void *p) { esp_apptrace_test_task_arg_t *arg = (esp_apptrace_test_task_arg_t *) p; int res, flags = 0, i; timer_isr_handle_t *inth = NULL; TickType_t tmo_ticks = arg->data.period / (1000 * portTICK_PERIOD_MS); ESP_APPTRACE_TEST_LOGI("%x: run dummy task (period %u us, %u timers)", xTaskGetCurrentTaskHandle(), arg->data.period, arg->timers_num); if (arg->timers_num > 0) { inth = pvPortMalloc(arg->timers_num * sizeof(timer_isr_handle_t)); if (!inth) { ESP_APPTRACE_TEST_LOGE("Failed to alloc timer ISR handles!"); goto on_fail; } memset(inth, 0, arg->timers_num * sizeof(timer_isr_handle_t)); for (int i = 0; i < arg->timers_num; i++) { esp_apptrace_test_timer_init(arg->timers[i].group, arg->timers[i].id, arg->timers[i].data.period); res = timer_isr_register(arg->timers[i].group, arg->timers[i].id, arg->timers[i].isr_func, &arg->timers[i], flags, &inth[i]); if (res != ESP_OK) { ESP_APPTRACE_TEST_LOGE("Failed to timer_isr_register (%d)!", res); goto on_fail; } *(uint32_t *)arg->timers[i].data.buf = (uint32_t)inth[i] | (1 << 31); ESP_APPTRACE_TEST_LOGI("%x: start timer %x period %u us", xTaskGetCurrentTaskHandle(), inth[i], arg->timers[i].data.period); res = timer_start(arg->timers[i].group, arg->timers[i].id); if (res != ESP_OK) { ESP_APPTRACE_TEST_LOGE("Failed to timer_start (%d)!", res); goto on_fail; } } } i = 0; while (!arg->stop) { ESP_APPTRACE_TEST_LOGD("%x: dummy task work %d.%d", xTaskGetCurrentTaskHandle(), xPortGetCoreID(), i++); if (tmo_ticks) { vTaskDelay(tmo_ticks); } } on_fail: if (inth) { for (int i = 0; i < arg->timers_num; i++) { timer_pause(arg->timers[i].group, arg->timers[i].id); timer_disable_intr(arg->timers[i].group, arg->timers[i].id); if (inth[i]) { esp_intr_free(inth[i]); } } vPortFree(inth); } xSemaphoreGive(arg->done); vTaskDelay(1); vTaskDelete(NULL); }
bool timers_remove(uint8_t position) { Timer* timer = timers_get(position); if (NULL == timer) { return false; } timer_pause(timer); linked_list_remove(timers, position); free(timer); timers_mark_updated(); return true; }
void timer_reset(Timer* timer) { timer_pause(timer); switch (timer->type) { case TIMER_TYPE_TIMER: timer->current_time = timer->length; break; case TIMER_TYPE_STOPWATCH: timer->current_time = 0; break; } timer->status = TIMER_STATUS_STOPPED; timers_mark_updated(); }
void buzzer_handler(void) { if (piezo_out) gpio_toggle_bit(PIN_MAP[BUZZER_PWM].gpio_device, PIN_MAP[BUZZER_PWM].gpio_bit); if (headphones_out) gpio_toggle_bit(PIN_MAP[HP_COMBINED].gpio_device,PIN_MAP[HP_COMBINED].gpio_bit); buzz_count++; if(buzz_count == buzz_time) { timer_pause(TIMER2); gpio_write_bit(PIN_MAP[BUZZER_PWM].gpio_device,PIN_MAP[BUZZER_PWM].gpio_bit,0); gpio_write_bit(PIN_MAP[HP_COMBINED].gpio_device,PIN_MAP[HP_COMBINED].gpio_bit,0); headphones_out = false; } }
void DmxClass::begin(uint16 n) { SerialUSB.println("DMX begin"); this->number_of_channels = n; // red, green, and blue are independent channels //SerialUSB.end(); // initializes timer configurations timer_pause(this->dmx_timer); timer_set_prescaler(this->dmx_timer, 1); timer_set_reload(this->dmx_timer, 288); // 4 us = 288 clock pulses @ 72MHz timer_generate_update(this->dmx_timer); // update new reload value timer_set_mode(this->dmx_timer, dmx_timer_ch, TIMER_OUTPUT_COMPARE); timer_set_compare(this->dmx_timer, dmx_timer_ch, 1); // test timer_attach_interrupt(this->dmx_timer, TIMER_CC1_INTERRUPT, dmx_handler_hack); timer_resume(this->dmx_timer); }
// This is my primary Event Loop. This is where most of the fun stuff happens ;) void Megamaniac() { // WTF does this do? Something to do with my Data Structure I assume... Game game; while (true) { // Let's run our initial setup to get everything for the game ready. SetupGame(&game); // Do we need to change the level? Not really but we should probably start at Level 1. ChangeLevel(&game); // This is where the Event Loop actually starts. This will run repeatedly until our game is over. while (!game.game_over) { clear_screen(); GameStats(&game); int userInput = UserInput(&game); MovementPlayer(&game, userInput); MovementMissiles(&game, userInput); MovementAliens(&game); MovementBombs(&game); MovementBonuses(&game); CollisionMissiles(&game); CollisionAliens(&game); CollisionBombs(&game); CollisionBonuses(&game); UpdateScreen(&game); show_screen(); timer_pause(25); } GameOver(&game); int userInput = wait_char(); while (userInput != 'r' && userInput >= 0) { if (userInput == 'q') { exit(0); } if (userInput == 'r') { Megamaniac(); } userInput = wait_char(); } } }
void key_down(SDL_Keycode k) { switch (k) { case SDLK_s: if (timer_is_started(t)) timer_stop(t); else timer_start(t); break; case SDLK_p: if (timer_is_paused(t)) timer_unpause(t); else timer_pause(t); break; } }
//TODO implement timeout uint_fast8_t mdns_resolve(const char *name, mDNS_Resolve_Cb cb, void *data) { if(resolve.cb) // is there a mDNS resolve request already ongoing? return 0; // construct DNS label from mDNS name char *ref = resolve.name; const char *s0 = name; char *s1; char len; while( (s1 = strchr(s0, '.')) ) { len = s1 - s0; *ref++ = len; memcpy(ref, s0, len); ref += len; s0 = s1 + 1; // skip '.' } len = strlen(s0); *ref++ = len; memcpy(ref, s0, len); ref += len; *ref++ = 0x0; // trailing zero resolve.cb = cb; resolve.data = data; // serialize and send mDNS name request uint8_t *head = BUF_O_OFFSET(buf_o_ptr); uint8_t *tail = head; uint16_t id = rand() & 0xffff; tail = _serialize_query(tail, id, 0, 1, 0, 0, 0); tail = _serialize_question(tail, resolve.name, MDNS_TYPE_A, MDNS_CLASS_INET); udp_send(config.mdns.socket.sock, BUF_O_BASE(buf_o_ptr), tail-head); // start timer for timeout timer_pause(mdns_timer); mdns_timer_reconfigure(); timer_resume(mdns_timer); return 1; }
static uint8_t * _dns_answer(DNS_Query *query, uint8_t *buf) { uint8_t *buf_ptr = buf; char *qname; buf_ptr = _unroll_qname(query, buf_ptr, &qname); DNS_Answer *answer =(DNS_Answer *)buf_ptr; answer->RTYPE = hton(answer->RTYPE); answer->RCLASS = hton(answer->RCLASS); answer->TTL = htonl(answer->TTL); answer->RLEN = hton(answer->RLEN); buf_ptr += sizeof(DNS_Answer); switch(answer->RTYPE) { case MDNS_TYPE_A: // ignore when qname was not requested by us previously if(!resolve.cb || strcmp(qname, resolve.name)) break; //TODO handle conflicts when probing uint8_t *ip = (uint8_t *)buf_ptr; if(ip_part_of_subnet(ip)) // check IP for same subnet TODO make this configurable { timer_pause(mdns_timer); // stop timeout timer resolve.cb(ip, resolve.data); // reset request resolve.name[0] = '\0'; resolve.cb = NULL; resolve.data = NULL; } break; default: // ignore remaining answer types, e.g MDNS_TYPE_PTR, MDNS_TYPE_SRV, MDNS_TYPE_TXT break; } buf_ptr += answer->RLEN; // skip rdata return buf_ptr; }
void buzzer_nonblocking_buzz(float time) { buzz_time = 4100*time*2; // Configure timer2 to fire every N microseconds timer_pause(TIMER2); timer_set_prescaler(TIMER2,1); timer_set_reload(TIMER2,(125*CYCLES_PER_MICROSECOND)/2); // setup interrupt on channel 2 timer_set_mode(TIMER2,TIMER_CH2,TIMER_OUTPUT_COMPARE); timer_set_compare(TIMER2,TIMER_CH2,MAX_RELOAD-1); timer_attach_interrupt(TIMER2,TIMER_CH2,buzzer_handler); // start timer2 buzz_count=0; timer_generate_update(TIMER2); // refresh timer count, prescale, overflow timer_resume(TIMER2); }
static void my_timer_init(int timer_group, int timer_idx, int ival) { timer_config_t config; config.alarm_en = 1; config.auto_reload = 1; config.counter_dir = TIMER_COUNT_UP; config.divider = TIMER_DIVIDER; config.intr_type = TIMER_INTR_LEVEL; config.counter_en = TIMER_PAUSE; /*Configure timer*/ timer_init(timer_group, timer_idx, &config); /*Stop timer counter*/ timer_pause(timer_group, timer_idx); /*Load counter value */ timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL); /*Set alarm value*/ timer_set_alarm_value(timer_group, timer_idx, ival); /*Enable timer interrupt*/ timer_enable_intr(timer_group, timer_idx); }
void demo() { const int N = 5; const double X_MAX = screen_width(); const double Y_MAX = screen_height(); double p[] = {0.5, 1, 1.5, 2, 3}; for (int i = 0; i < N; i++) { clear_screen(); double x0 = X_MAX / 2; double y0 = Y_MAX / 2; double xr = X_MAX / 3; double yr = Y_MAX / 3; draw_ellipse_p(x0, y0, xr, yr, p[i], '*'); draw_string(0, 0, "p = "); draw_double(4, 0, p[i]); show_screen(); timer_pause(5000); } }
void DmxClass::handler(void) { digitalWrite(this->dmx_tx1_pin, this->bitBuffer); if (this->channelIndex == this->number_of_channels) { timer_pause(this->dmx_timer); this->bitBuffer = END_OF_PACKET_BIT; if (DEBUG_LED) { toggleLED(); } SerialUSB.println("end of packet"); } else if (this->headerIndex < SIZE_OF_HEADER) { SerialUSB.print(headerIndex, DEC); this->bitBuffer = this->header(); headerIndex++; if (headerIndex >= SIZE_OF_HEADER) { SerialUSB.println(); } } else { switch ( this->bitIndex ) { case 0: this->bitBuffer = START_BIT; this->bitIndex++; SerialUSB.print("chan: "); SerialUSB.println(channelIndex, DEC); break; case 10: this->bitBuffer = STOP_BIT; this->bitIndex = 0; this->channelIndex++; SerialUSB.println(); break; case 9: this->bitBuffer = STOP_BIT; this->bitIndex++; break; default: // channel data: cases 1 through 8 this->bitBuffer = bitRead(this->channel[this->channelIndex], this->bitIndex - 1); SerialUSB.print(bitBuffer, DEC); this->bitIndex++; break; } } }
static void example_timer_init(int timer_group, int timer_idx, uint32_t period) { timer_config_t config; uint64_t alarm_val = (period * (TIMER_BASE_CLK / 1000000UL)) / 2; config.alarm_en = 1; config.auto_reload = 1; config.counter_dir = TIMER_COUNT_UP; config.divider = 2; //Range is 2 to 65536 config.intr_type = TIMER_INTR_LEVEL; config.counter_en = TIMER_PAUSE; /*Configure timer*/ timer_init(timer_group, timer_idx, &config); /*Stop timer counter*/ timer_pause(timer_group, timer_idx); /*Load counter value */ timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL); /*Set alarm value*/ timer_set_alarm_value(timer_group, timer_idx, alarm_val); /*Enable timer interrupt*/ timer_enable_intr(timer_group, timer_idx); }
void HardwareTimer::pause(void) { timer_pause(this->dev); }
void play_ten_squares() { clear_screen(); draw_string( 0, screen_height() - 1, "Press any key to continue..." ); show_screen(); wait_char(); char bitmap1[] = "11111111" "1 1" "1 1" "1 1" "1 1" "1 1" "1 1" "11111111" ; char bitmap2[] = "11111" "1 1" "1 1" "1 1" "11111" ; char bitmap3[] = { "111111111111" "1 1" "1 1" "1 1" "1 1" "1 1" "1 1" "111111111111" }; char *bitmaps[3] = { bitmap1, bitmap2, bitmap3 }; char widths[] = { 8, 5, 12 }; char heights[] = { 8, 5, 8 }; #define SPR_COUNT (10) sprite_id sprites[SPR_COUNT]; setup_ten_squares( sprites, bitmaps, widths, heights, SPR_COUNT, sizeof( bitmaps ) / sizeof( bitmaps[0] ) ); int key = 0; while ( key != 'q' ) { clear_screen(); update_ten_squares( sprites ); draw_ten_squares( sprites ); draw_string( 0, screen_height() - 1, "Press 'q' to exit..." ); show_screen(); timer_pause( 50 ); key = get_char(); } cleanup_ten_squares( sprites ); }
void zombie_racer(int start_x, int start_y) { sprite_id racetrack = generate_racetrack(); int x = start_x; int y = start_y; int dir = 0; // Start facing North. bool alive = on_racetrack(x, y); update_view(racetrack, x, y, alive); int key = wait_char(); while ((key != 'q') && (key >= 0) && alive) { switch (key) { case '1': dir = (dir + 7) % 8; break; case '3': dir = (dir + 1) % 8; break; } switch (dir) { case 0: y--; break; case 1: y--; x++; break; case 2: x++; break; case 3: x++; y++; break; case 4: y++; break; case 5: y++; x--; break; case 6: x--; break; case 7: x--; y--; break; } alive = on_racetrack(x, y); update_view(racetrack, x, y, alive); timer_pause(100); key = wait_char(); } free(racetrack->bitmap); racetrack->bitmap = NULL; destroy_sprite(racetrack); timer_pause(1000); }