int get_data(struct trigger_t *trigger, struct can_frame *frame) { uint16_t crc; if (frame->can_dlc == 6) { trigger->length = (frame->data[2] << 8) | frame->data[3]; trigger->crc = (frame->data[4] << 8) | frame->data[5]; printf("length 0x%04x crc 0x%04x\n", trigger->length, trigger->crc); trigger->data = (uint8_t *) calloc(trigger->length + 1, 1); if (!trigger->data) { fprintf(stderr, "can't alloc memory for config data: %s\n", strerror(errno)); return (EXIT_FAILURE); } trigger->data_index = 0; return 0; } if (trigger->data_index < trigger->length) { memcpy(&trigger->data[trigger->data_index], frame->data, 8); trigger->data_index += 8; } else { printf("Error: unexpected data\n"); return (EXIT_FAILURE); } if (trigger->data_index == trigger->length) { if (!trigger->background && trigger->verbose) printf("data complete %d %d\n", trigger->data_index, trigger->length); crc = CRCCCITT(trigger->data, trigger->length, 0xFFFF); if (crc == trigger->crc) { if (!trigger->background && trigger->verbose) printf("crc 0x%04x 0x%04x\n", crc, trigger->crc); strip_ms2_spaces(trigger->data, trigger->length); } printf("Data:\n%s\n", trigger->data); read_loco_data((char *)trigger->data, CONFIG_STRING); print_locos(); printf("max locos : %d\n", get_loco_max()); set_led_pattern(trigger, LED_ST_HB_SLOW); free(trigger->data); } return 0; }
int main(int argc, char **argv) { pthread_t pth; int opt; struct ifreq ifr; struct trigger_t trigger_data; struct sockaddr_can caddr; fd_set readfds, exceptfds; struct can_frame frame; uint16_t member; uint8_t buffer[MAXLEN]; memset(&trigger_data, 0, sizeof(trigger_data)); memset(ifr.ifr_name, 0, sizeof(ifr.ifr_name)); strcpy(ifr.ifr_name, "can0"); trigger_data.led_pin = -1; trigger_data.pb_pin = -1; trigger_data.interval = DEF_INTERVAL; while ((opt = getopt(argc, argv, "i:l:p:t:fvh?")) != -1) { switch (opt) { case 'i': strncpy(ifr.ifr_name, optarg, sizeof(ifr.ifr_name)); break; case 't': trigger_data.interval = atoi(optarg); break; case 'l': trigger_data.led_pin = atoi(optarg); break; case 'p': trigger_data.pb_pin = atoi(optarg); break; case 'v': trigger_data.verbose = 1; break; case 'f': trigger_data.background = 0; break; case 'h': case '?': usage(basename(argv[0])); exit(EXIT_SUCCESS); default: usage(basename(argv[0])); exit(EXIT_FAILURE); } } /* prepare CAN socket */ if ((trigger_data.socket = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { fprintf(stderr, "error creating CAN socket: %s\n", strerror(errno)); exit(EXIT_FAILURE); } memset(&caddr, 0, sizeof(caddr)); caddr.can_family = AF_CAN; if (ioctl(trigger_data.socket, SIOCGIFINDEX, &ifr) < 0) { fprintf(stderr, "setup CAN socket error: %s %s\n", strerror(errno), ifr.ifr_name); exit(EXIT_FAILURE); } caddr.can_ifindex = ifr.ifr_ifindex; if (bind(trigger_data.socket, (struct sockaddr *)&caddr, sizeof(caddr)) < 0) { fprintf(stderr, "error binding CAN socket: %s\n", strerror(errno)); exit(EXIT_FAILURE); } trigger_data.caddr = caddr; /* Create thread if LED pin defined */ if ((trigger_data.led_pin) > 0) { trigger_data.led_pattern = LED_ST_HB_SLOW; gpio_export(trigger_data.led_pin); gpio_direction(trigger_data.led_pin, 0); if (pthread_mutex_init(&lock, NULL)) { fprintf(stderr, "can't init mutex %s\n", strerror(errno)); exit(EXIT_FAILURE); } if (pthread_create(&pth, NULL, LEDMod, &trigger_data)) { fprintf(stderr, "can't create pthread %s\n", strerror(errno)); exit(EXIT_FAILURE); } if (!trigger_data.background && trigger_data.verbose) printf("created LED thread\n"); } if (trigger_data.background) { pid_t pid; /* fork off the parent process */ pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } /* if we got a good PID, then we can exit the parent process. */ if (pid > 0) { if (trigger_data.verbose) printf("Going into background ...\n"); exit(EXIT_SUCCESS); } } /* initialize push button */ if ((trigger_data.pb_pin) > 0) { /* first free pin */ gpio_unexport(trigger_data.pb_pin); gpio_export(trigger_data.pb_pin); gpio_direction(trigger_data.pb_pin, 1); gpio_edge(trigger_data.pb_pin, EDGE_FALLING); trigger_data.pb_fd = gpio_open(trigger_data.pb_pin); } FD_ZERO(&readfds); FD_ZERO(&exceptfds); /* delete pending push button event */ if ((trigger_data.pb_pin) > 0) { read(trigger_data.pb_fd, NULL, 100); lseek(trigger_data.pb_fd, 0, SEEK_SET); } /* loop forever TODO: if interval is set */ while (1) { FD_SET(trigger_data.socket, &readfds); /* extend FD_SET only if push button pin is set */ if (trigger_data.pb_pin > 0) FD_SET(trigger_data.pb_fd, &exceptfds); if (select(MAX(trigger_data.socket, trigger_data.pb_fd) + 1, &readfds, NULL, &exceptfds, NULL) < 0) { fprintf(stderr, "select error: %s\n", strerror(errno)); exit(EXIT_FAILURE); } /* CAN frame event */ if (FD_ISSET(trigger_data.socket, &readfds)) { if (read(trigger_data.socket, &frame, sizeof(struct can_frame)) < 0) fprintf(stderr, "error reading CAN frame: %s\n", strerror(errno)); if (frame.can_id & CAN_EFF_FLAG) { switch ((frame.can_id & 0x00FF0000UL) >> 16) { case 0x31: if (trigger_data.verbose) print_can_frame(F_CAN_FORMAT_STRG, &frame); memcpy(&member, frame.data, sizeof(member)); member = ntohs(member); /* look for MS2 */ if ((member & 0xfff0) == 0x4d50) get_ms2_dbsize(&trigger_data); break; case 0x41: if (trigger_data.verbose) print_can_frame(F_CAN_FORMAT_STRG, &frame); break; case 0x42: get_data(&trigger_data, &frame); /* if (trigger_data.verbose) print_can_frame(F_CAN_FORMAT_STRG, &frame); */ break; default: if (trigger_data.verbose) print_can_frame(F_CAN_FORMAT_STRG, &frame); break; } } } /* push button event */ if (FD_ISSET(trigger_data.pb_fd, &exceptfds)) { set_led_pattern(&trigger_data, LED_ST_HB_FAST); /* wait some time for LED pattern change */ usec_sleep(1000 * 1000); /* send CAN Member Ping */ frame.can_id = 0x00300300; frame.can_dlc = 0; memset(frame.data, 0, 8); if (send_can_frame(trigger_data.socket, &frame, trigger_data.verbose) < 0) fprintf(stderr, "can't send CAN Member Ping: %s\n", strerror(errno)); lseek(trigger_data.pb_fd, 0, SEEK_SET); if (read(trigger_data.pb_fd, buffer, sizeof(buffer)) < 0) fprintf(stderr, "error reading GPIO status: %s\n", strerror(errno)); printf("push button event\n"); } } /* TODO : wait until copy is done */ if ((trigger_data.pb_pin) > 0) gpio_unexport(trigger_data.pb_pin); if ((trigger_data.led_pin) > 0) { gpio_unexport(trigger_data.led_pin); pthread_join(pth, (void *)&trigger_data); pthread_mutex_unlock(&lock); } return 0; }
int main(void) { uint8_t id, rec, i, cs; color_t c; packet_t p; setup(); stop_motor(); sei(); for(i = 0; i < 5; i++) { set_led_rgb(255, 0, 255); _delay_ms(50); set_led_rgb(255, 255, 0); _delay_ms(50); } // get the current liquid level update_liquid_level(); for(;;) { cli(); g_reset = 0; g_current_sense_detected = 0; g_current_sense_num_cycles = 0; setup(); serial_init(); stop_motor(); set_led_rgb(0, 0, 255); sei(); id = address_exchange(); for(; !check_reset();) { rec = receive_packet(&p); if (rec == COMM_CRC_FAIL) continue; if (rec == COMM_RESET) break; if (rec == COMM_OK && (p.dest == DEST_BROADCAST || p.dest == id)) { // If we've detected a over current sitatuion, ignore all comamnds until reset cli(); cs = g_current_sense_detected; sei(); switch(p.type) { case PACKET_PING: break; case PACKET_SET_MOTOR_SPEED: if (!cs) set_motor_speed(p.p.uint8[0], p.p.uint8[1]); if (p.p.uint8[0] == 0) flush_saved_tick_count(0); break; case PACKET_TICK_DISPENSE: if (!cs) { dispense_ticks((uint16_t)p.p.uint32, 255); flush_saved_tick_count(0); } break; case PACKET_TIME_DISPENSE: if (!cs) { run_motor_timed(p.p.uint32); flush_saved_tick_count(0); } break; case PACKET_IS_DISPENSING: is_dispensing(); break; case PACKET_LIQUID_LEVEL: get_liquid_level(); break; case PACKET_UPDATE_LIQUID_LEVEL: update_liquid_level(); break; case PACKET_LED_OFF: set_led_pattern(LED_PATTERN_OFF); break; case PACKET_LED_IDLE: if (!cs) set_led_pattern(LED_PATTERN_IDLE); break; case PACKET_LED_DISPENSE: if (!cs) set_led_pattern(LED_PATTERN_DISPENSE); break; case PACKET_LED_DRINK_DONE: if (!cs) set_led_pattern(LED_PATTERN_DRINK_DONE); break; case PACKET_LED_CLEAN: if (!cs) set_led_pattern(LED_PATTERN_CLEAN); break; case PACKET_COMM_TEST: comm_test(); break; case PACKET_ID_CONFLICT: id_conflict(); break; case PACKET_SET_CS_THRESHOLD: g_current_sense_threshold = p.p.uint16[0]; break; case PACKET_SAVED_TICK_COUNT: get_saved_tick_count(); break; case PACKET_RESET_SAVED_TICK_COUNT: reset_saved_tick_count(); break; case PACKET_FLUSH_SAVED_TICK_COUNT: flush_saved_tick_count(1); break; case PACKET_GET_LIQUID_THRESHOLDS: get_liquid_thresholds(); break; case PACKET_SET_LIQUID_THRESHOLDS: set_liquid_thresholds(p.p.uint16[0], p.p.uint16[1]); break; case PACKET_TICK_SPEED_DISPENSE: if (!cs) { dispense_ticks(p.p.uint16[0], (uint8_t)p.p.uint16[1]); flush_saved_tick_count(0); } break; case PACKET_PATTERN_DEFINE: pattern_define(p.p.uint8[0]); break; case PACKET_PATTERN_ADD_SEGMENT: c.red = p.p.uint8[0]; c.green = p.p.uint8[1]; c.blue = p.p.uint8[2]; pattern_add_segment(&c, p.p.uint8[3]); break; case PACKET_PATTERN_FINISH: pattern_finish(); break; } } } } return 0; }
void text_interface(void) { char cmd[MAX_CMD_LEN]; uint8_t speed, current_sense; uint16_t ticks; uint16_t t; uint8_t i, cs; for(i = 0; i < 5; i++) { set_led_rgb(0, 0, 255); _delay_ms(150); set_led_rgb(0, 0, 0); _delay_ms(150); } set_led_pattern(LED_PATTERN_IDLE); for(;;) { cli(); g_reset = 0; g_current_sense_detected = 0; setup(); stop_motor(); serial_init(); cs = 0; sei(); _delay_ms(10); dprintf("\nParty Robotics Dispenser at your service!\n\n"); for(;;) { cli(); cs = g_current_sense_detected; sei(); if (!receive_cmd(cmd)) break; if (sscanf(cmd, "speed %hhu %hhu", &speed, ¤t_sense) == 2) { if (!cs) set_motor_speed(speed, current_sense); if (current_sense == 0) flush_saved_tick_count(0); continue; } if (sscanf(cmd, "tickdisp %hu %hhu", (short unsigned int *)&ticks, &speed) == 2) { if (!cs) { dispense_ticks(ticks, speed); flush_saved_tick_count(0); } continue; } if (sscanf(cmd, "timedisp %hu", (short unsigned int *)&t) == 1) { if (!cs) { run_motor_timed(t); flush_saved_tick_count(0); } continue; } if (strncmp(cmd, "forward", 7) == 0) { set_motor_direction(MOTOR_DIRECTION_FORWARD); continue; } if (strncmp(cmd, "backward", 8) == 0) { set_motor_direction(MOTOR_DIRECTION_BACKWARD); continue; } if (strncmp(cmd, "led_idle", 8) == 0) { set_led_pattern(LED_PATTERN_IDLE); continue; } if (strncmp(cmd, "led_dispense", 12) == 0) { set_led_pattern(LED_PATTERN_DISPENSE); continue; } if (strncmp(cmd, "led_done", 8) == 0) { set_led_pattern(LED_PATTERN_DRINK_DONE); continue; } if (strncmp(cmd, "led_clean", 8) == 0) { set_led_pattern(LED_PATTERN_CLEAN); continue; } if (strncmp(cmd, "help", 4) == 0) { dprintf("You can use these commands:\n"); dprintf(" speed <speed> <cs>\n"); dprintf(" tickdisp <ticks> <speed>\n"); dprintf(" timedisp <ms>\n"); dprintf(" forward\n"); dprintf(" backward\n"); dprintf(" reset\n"); dprintf(" led_idle\n"); dprintf(" led_dispense\n"); dprintf(" led_done\n"); dprintf(" led_clean\n\n"); dprintf("speed is from 0 - 255. cs = current sense and is 0 or 1.\n"); dprintf("ticks == number of quarter turns. ms == milliseconds\n"); continue; } if (strncmp(cmd, "reset", 5) == 0) break; dprintf("Unknown command. Use help to get, eh help. Duh.\n"); } } }