static int mbox_property(int file_desc, void *buf) { int fd = file_desc; int ret_val = -1; if (fd < 0) { fd = mbox_open(); } if (fd >= 0) { ret_val = ioctl(fd, IOCTL_MBOX_PROPERTY, buf); if (ret_val < 0) { printf("ioctl_set_msg failed, errno %d: %m\n", errno); } } #ifdef DEBUG unsigned *p = buf; int i; unsigned size = *(unsigned *)buf; for (i=0; i<size/4; i++) printf("%04x: 0x%08x\n", i*sizeof *p, p[i]); #endif if (file_desc < 0) mbox_close(fd); return ret_val; }
static void terminate(int dummy) { int i; dprintf("Resetting DMA...\n"); if (dma_reg && mbox.virt_addr) { for (i = 0; i < num_channels; i++) channel_pwm[i] = 0; update_pwm(); udelay(CYCLE_TIME_US); dma_reg[DMA_CS] = DMA_RESET; udelay(10); } dprintf("Freeing mbox memory...\n"); if (mbox.virt_addr != NULL) { unmapmem(mbox.virt_addr, NUM_PAGES * PAGE_SIZE); if (mbox.handle <= 2) { /* we need to reopen mbox file */ mbox.handle = mbox_open(); } mem_unlock(mbox.handle, mbox.mem_ref); mem_free(mbox.handle, mbox.mem_ref); mbox_close(mbox.handle); } dprintf("Unlink %s...\n", DEVFILE); unlink(DEVFILE); dprintf("Unlink %s...\n", DEVFILE_MBOX); unlink(DEVFILE_MBOX); printf("pi-blaster stopped.\n"); exit(1); }
/** * Cleanup previously allocated device memory and buffers. * * @param ws2811 ws2811 instance pointer. * * @returns None */ void ws2811_cleanup(ws2811_t *ws2811) { int chan; for (chan = 0; chan < RPI_PWM_CHANNELS; chan++) { if (ws2811->channel[chan].leds) { free(ws2811->channel[chan].leds); } ws2811->channel[chan].leds = NULL; } if (mbox.virt_addr != NULL) { unmapmem(mbox.virt_addr, mbox.size); mem_unlock(mbox.handle, mbox.mem_ref); mem_free(mbox.handle, mbox.mem_ref); if (mbox.handle >= 0) mbox_close(mbox.handle); memset(&mbox, 0, sizeof(mbox)); } ws2811_device_t *device = ws2811->device; if (device) { free(device); } ws2811->device = NULL; }
/** * Cleanup previously allocated device memory and buffers. * * @param ws2811 ws2811 instance pointer. * * @returns None */ void ws2811_cleanup(ws2811_t *ws2811) { ws2811_device_t *device = ws2811->device; int chan; for (chan = 0; chan < RPI_PWM_CHANNELS; chan++) { if (ws2811->channel[chan].leds) { free(ws2811->channel[chan].leds); } ws2811->channel[chan].leds = NULL; } if (device->mbox.handle != -1) { videocore_mbox_t *mbox = &device->mbox; unmapmem(mbox->virt_addr, mbox->size); mem_unlock(mbox->handle, mbox->mem_ref); mem_free(mbox->handle, mbox->mem_ref); mbox_close(mbox->handle); mbox->handle = -1; } if (device) { free(device); } ws2811->device = NULL; }
int main(int argc, char *argv[]) { int mb = mbox_open(); unsigned words[MAX_WORDS] = {}; int i; if (argc < 2 || argc+1 >= MAX_WORDS) { printf("Usage %s [word0] [word1] ...\n", argv[0]); return 1; } words[0] = (argc+2) * sizeof words[0]; words[1] = 0; // process request for (i=1; i<argc; i++) words[i+1] = strtoul(argv[i], 0, 0); words[argc+1] = 0; // end tag int s = mbox_property(mb, words); mbox_close(mb); for (i=0; i<argc+2; i++) printf("0x%08x ", words[i]); printf("\n"); return s; }
void mbox_deinit(void) { // Remove any envelope symbols lcd_symbol_clr(LCD_SYMBOL_ENV_MAIN); lcd_symbol_clr(LCD_SYMBOL_ENV_CL); lcd_symbol_clr(LCD_SYMBOL_ENV_OP); // Close mailbox and indicate no longer initialized mbox_close(); mbox_initalized = false; }
void main (int argc, char *argv[]) { char so4[SO4_SIZE] = {'S', 'O', '4'}; mbox_t h_mbox; // Handle to the mailbox sem_t s_procs_completed; // Semaphore to signal the original process that we're done if (argc != 3) { Printf("Usage: %s <handle_to_mailbox> <handle_to_page_mapped_semaphore>\n"); Exit(); } // Convert the command-line strings into integers for use as handles h_mbox = dstrtol(argv[1], NULL, 10); // The "10" means base 10 s_procs_completed = dstrtol(argv[2], NULL, 10); // Open the mailbox if (mbox_open(h_mbox) == MBOX_FAIL) { Printf("Generator SO4 (%d): Could not open the mailbox!\n", getpid()); Exit(); } // Send a message to the mailbox if (mbox_send(h_mbox, SO4_SIZE, (void *) so4) == MBOX_FAIL) { Printf("Generator SO4 (%d): Could not send message to the mailbox %d!\n", getpid(), h_mbox); Exit(); } // Now print a message to show that everything worked Printf("Generate SO4 Molecule\n"); // Close the mbox if (mbox_close(h_mbox) == MBOX_FAIL) { Printf("Generator SO4 (%d): Could not close the mailbox!\n", getpid()); Exit(); } // Signal the semaphore to tell the original process that we're done if(sem_signal(s_procs_completed) != SYNC_SUCCESS) { Printf("Generator SO4 (%d): Bad semaphore s_procs_completed (%d)!\n", getpid(), s_procs_completed); Exit(); } Printf("Generator SO4 (%d): Done!\n", getpid()); }
void main (int argc, char *argv[]) { sem_t s_procs_completed; // Semaphore to signal the original process that we're done mbox_t mb_n2; // mailbox for H2O atom Printf("Starting N2 Injection - PID %d \n", getpid()); if (argc > 4 ) { Printf("Usage: "); Printf(argv[0]); Printf(" <handle_to_proc_semaphore> <handle_to_N2_mailbox>\n"); Exit(); } // Convert the command-line strings into integers for use as handles s_procs_completed = dstrtol(argv[1], NULL, 10); mb_n2 = dstrtol(argv[2], NULL, 10); if(!mbox_open(mb_n2)){ Printf("Bad mailbox open mb_n2\n"); Exit(); } Printf("opened n2 mailbox\n"); if(mbox_send(mb_n2, 2, (void *) "N2") != MBOX_SUCCESS){ Printf("N2 send error\n"); } Printf("Sent N2 to mb_n2\n"); if(!mbox_close(mb_n2)){ Printf("Bad mailbox open mb_n2\n"); Exit(); } // Signal the semaphore to tell the original process that we're done Printf("Inject N2: PID %d is complete.\n", getpid()); if(sem_signal(s_procs_completed) != SYNC_SUCCESS) { Printf("Bad semaphore s_procs_completed (%d) in ", s_procs_completed); Printf(argv[0]); Printf(", exiting...\n"); Exit(); } }
static int mbox_property(int file_desc, void *buf) { int fd = file_desc; int ret_val = -1; if (fd < 0) { fd = mbox_open(); } if (fd >= 0) { ret_val = ioctl(fd, IOCTL_MBOX_PROPERTY, buf); if (ret_val < 0) { perror("ioctl_set_msg failed\n"); } } if (file_desc < 0) { mbox_close(fd); } return ret_val; }
int mbox_open(void) { // Return if not initialized if (mbox_initalized == false) { return EOF; } // If allready open, close first if (mbox_is_open == true) { mbox_close(); } // Start file rading at start of data flash sfs_fget_restart(); // allocate memory for mail reading if ((mbox_mail_element = (mbox_mail_element_t*)vrt_mem_alloc(/*sizeof(mbox_mail_element_t)*/ + 64)) == NULL) { return EOF; } else { mbox_is_open = true; return 0; } }
void main (int argc, char *argv[]) { int ct; char h2o_buffer_1[H2O_SIZE]; char h2o_buffer_2[H2O_SIZE]; char h2_molecule[H2_SIZE] = {'H', '2'}; char o2_molecule[O2_SIZE] = {'O', '2'}; mbox_t h_mbox_h2o; // Handle to the mailbox for h2o mbox_t h_mbox_h2; mbox_t h_mbox_o2; sem_t s_procs_completed; // Semaphore to signal the original process that we're done if (argc != 5) { Printf("Usage: %s <mailbox h2o> <mailbox h2> <mailbox o2> <handle_to_page_mapped_semaphore>\n"); Exit(); } // Convert the command-line strings into integers for use as handles h_mbox_h2o = dstrtol(argv[1], NULL, 10); // The "10" means base 10 h_mbox_h2 = dstrtol(argv[2], NULL, 10); // The "10" means base 10 h_mbox_o2 = dstrtol(argv[3], NULL, 10); // The "10" means base 10 s_procs_completed = dstrtol(argv[4], NULL, 10); // Open the h2o mailbox if (mbox_open(h_mbox_h2o) == MBOX_FAIL) { Printf("Reaction 1 (%d): Could not open the h2o mailbox!\n", getpid()); Exit(); } // Wait for the first h2o molecule from the mailbox if (mbox_recv(h_mbox_h2o, H2O_SIZE, (void *) h2o_buffer_1) == MBOX_FAIL) { Printf("Reaction 1 (%d): Could not receive message from the mbox %d!\n", getpid(), h_mbox_h2o); Exit(); } // Wait for the second h2o molecule from the mailbox if (mbox_recv(h_mbox_h2o, H2O_SIZE, (void *) h2o_buffer_2) == MBOX_FAIL) { Printf("Reaction 1 (%d): Could not receive message from the mbox %d!\n", getpid(), h_mbox_h2o); Exit(); } // Close the h2o mailbox if (mbox_close(h_mbox_h2o) == MBOX_FAIL) { Printf("Reaction 1 (%d): Could not close the mailbox!\n", getpid()); Exit(); } // Open the h2 mailbox if (mbox_open(h_mbox_h2) == MBOX_FAIL) { Printf("Reaction 1 (%d): Could not open the h2 mailbox!\n", getpid()); Exit(); } // Send the first h2 to the h2 mailbox if (mbox_send(h_mbox_h2, H2_SIZE, (void *) h2_molecule) == MBOX_FAIL) { Printf("Generator h2 (%d): Could not send message to the mbox %d!\n", getpid(), h_mbox_h2); Exit(); } // Send the second h2 to the h2 mailbox if (mbox_send(h_mbox_h2, H2_SIZE, (void *) h2_molecule) == MBOX_FAIL) { Printf("Generator h2 (%d): Could not send message to the mbox %d!\n", getpid(), h_mbox_h2); Exit(); } // Close the h2 mailbox if (mbox_close(h_mbox_h2) == MBOX_FAIL) { Printf("Generator h2 (%d): Could not close the mailbox!\n", getpid()); Exit(); } // Open the o2 mailbox if (mbox_open(h_mbox_o2) == MBOX_FAIL) { Printf("Reaction 1 (%d): Could not open the o2 mailbox!\n", getpid()); Exit(); } // Send the o2 to the o2 mailbox if (mbox_send(h_mbox_o2, O2_SIZE, (void *) o2_molecule) == MBOX_FAIL) { Printf("Reaction o2 (%d): Could not send message to the mbox %d!\n", getpid(), h_mbox_o2); Exit(); } // Close the o2 mailbox if (mbox_close(h_mbox_o2) == MBOX_FAIL) { Printf("Reaction o2 (%d): Could not close the mailbox!\n", getpid()); Exit(); } // Now print a message to show that everything worked Printf("Two molecules H2 has been generated\n"); Printf("A molecule O2 has been generated\n"); // Signal the semaphore to tell the original process that we're done if(sem_signal(s_procs_completed) != SYNC_SUCCESS) { Printf("Reaction 1 (%d): Bad semaphore s_procs_completed (%d)!\n", getpid(), s_procs_completed); Exit(); } Printf("Reaction 1 (%d): Done!\n", getpid()); }
int main(int argc, char **argv) { parseargs(argc, argv); mbox.handle = mbox_open(); if (mbox.handle < 0) fatal("Failed to open mailbox\n"); unsigned mbox_board_rev = get_board_revision(mbox.handle); printf("MBox Board Revision: %#x\n", mbox_board_rev); get_model(mbox_board_rev); unsigned mbox_dma_channels = get_dma_channels(mbox.handle); printf("DMA Channels Info: %#x, using DMA Channel: %d\n", mbox_dma_channels, DMA_CHAN_NUM); printf("Using hardware: %5s\n", delay_hw == DELAY_VIA_PWM ? "PWM" : "PCM"); printf("Number of channels: %5d\n", (int)num_channels); printf("PWM frequency: %5d Hz\n", 1000000/CYCLE_TIME_US); printf("PWM steps: %5d\n", NUM_SAMPLES); printf("Maximum period (100 %%): %5dus\n", CYCLE_TIME_US); printf("Minimum period (%1.3f%%): %5dus\n", 100.0*SAMPLE_US / CYCLE_TIME_US, SAMPLE_US); printf("DMA Base: %#010x\n", DMA_BASE); setup_sighandlers(); /* map the registers for all DMA Channels */ dma_virt_base = map_peripheral(DMA_BASE, (DMA_CHAN_SIZE * (DMA_CHAN_MAX + 1))); /* set dma_reg to point to the DMA Channel we are using */ dma_reg = dma_virt_base + DMA_CHAN_NUM * (DMA_CHAN_SIZE / sizeof(dma_reg)); pwm_reg = map_peripheral(PWM_BASE, PWM_LEN); pcm_reg = map_peripheral(PCM_BASE, PCM_LEN); clk_reg = map_peripheral(CLK_BASE, CLK_LEN); gpio_reg = map_peripheral(GPIO_BASE, GPIO_LEN); /* Use the mailbox interface to the VC to ask for physical memory */ mbox.mem_ref = mem_alloc(mbox.handle, NUM_PAGES * PAGE_SIZE, PAGE_SIZE, mem_flag); /* TODO: How do we know that succeeded? */ dprintf("mem_ref %u\n", mbox.mem_ref); mbox.bus_addr = mem_lock(mbox.handle, mbox.mem_ref); dprintf("bus_addr = %#x\n", mbox.bus_addr); mbox.virt_addr = mapmem(BUS_TO_PHYS(mbox.bus_addr), NUM_PAGES * PAGE_SIZE); dprintf("virt_addr %p\n", mbox.virt_addr); if ((unsigned long)mbox.virt_addr & (PAGE_SIZE-1)) fatal("pi-blaster: Virtual address is not page aligned\n"); /* we are done with the mbox */ mbox_close(mbox.handle); mbox.handle = -1; //fatal("TempFatal\n"); init_ctrl_data(); init_hardware(); init_channel_pwm(); // Init pin2gpio array with 0/false values to avoid locking all of them as PWM. init_pin2gpio(); // Only calls update_pwm after ctrl_data calculates the pin mask to unlock all pins on start. init_pwm(); unlink(DEVFILE); if (mkfifo(DEVFILE, 0666) < 0) fatal("pi-blaster: Failed to create %s: %m\n", DEVFILE); if (chmod(DEVFILE, 0666) < 0) fatal("pi-blaster: Failed to set permissions on %s: %m\n", DEVFILE); printf("Initialised, "); if (daemonize) { if (daemon(0,1) < 0) fatal("pi-blaster: Failed to daemonize process: %m\n"); else printf("Daemonized, "); } printf("Reading %s.\n", DEVFILE); go_go_go(); return 0; }
void main (int argc, char *argv[]) { int numprocs; // Used to store number of processes to create int i; // Loop index variable missile_code mc; // Used as message for mailbox int num_N2; //numer of N2 injection int num_H2O; //number of H2O injection int num_N2_2N; //number of reaction1 int num_H2O_H2_O2; //number of reaction2 int num_N_O2_NO2; //number of reaction3 int number_N2; //number of N2 molecules int number_H2O; //number of H2O molecules mbox_t mbox_N2; //N2 mailbox mbox_t mbox_N; //N mailbox mbox_t mbox_H2O; //H2O mailbox mbox_t mbox_H2; //H2 mailbox mbox_t mbox_O2; //O2 mailbox mbox_t mbox_NO2; //NO2 mailbox sem_t s_procs_completed; // Semaphore used to wait until all spawned processes have completed char mbox_N2_str[10]; // Used as command-line argument to pass mem_handle to new processes char mbox_N_str[10]; char mbox_H2O_str[10]; char mbox_H2_str[10]; char mbox_O2_str[10]; char mbox_NO2_str[10]; char s_procs_completed_str[10]; // Used as command-line argument to pass page_mapped handle to new processes if (argc != 3) { Printf("Usage: ");Printf(argv[0]);Printf("<number of N2 molecules> <number of H2O molecules\n"); Exit(); } // Convert string from ascii command line argument to integer number number_N2 = dstrtol(argv[1],NULL,10); //the "10" means base 10 number_H2O = dstrtol(argv[2],NULL,10); if(number_H2O%2 ==1){ num_H2O = number_H2O; num_H2O_H2_O2 = (number_H2O-1)/2; num_N2 = number_N2; num_N2_2N = number_N2; if (2*num_N2>num_H2O_H2_O2){ //number of N larger than number of O2 num_N_O2_NO2 = num_H2O_H2_O2; } else{ num_N_O2_NO2 = 2*num_N2; } } else{ num_H2O = number_H2O; num_H2O_H2_O2 =(number_H2O)/2; num_N2 = number_N2; num_N2_2N = number_N2; if (2*num_N2>num_H2O_H2_O2){ //number of N larger than number of O2 num_N_O2_NO2 = num_H2O_H2_O2; } else{ num_N_O2_NO2 = 2*num_N2; } } numprocs=num_H2O+num_N2+num_H2O_H2_O2+num_N2_2N+num_N_O2_NO2; // Allocate space for a mailbox if ((mbox_N2 = mbox_create()) == MBOX_FAIL) { Printf("makeprocs (%d): ERROR: could not allocate mailbox!", getpid()); Exit(); } if ((mbox_N = mbox_create()) == MBOX_FAIL) { Printf("makeprocs (%d): ERROR: could not allocate mailbox!", getpid()); Exit(); } if ((mbox_O2 = mbox_create()) == MBOX_FAIL) { Printf("makeprocs (%d): ERROR: could not allocate mailbox!", getpid()); Exit(); } if ((mbox_NO2 = mbox_create()) == MBOX_FAIL) { Printf("makeprocs (%d): ERROR: could not allocate mailbox!", getpid()); Exit(); } if ((mbox_H2O = mbox_create()) == MBOX_FAIL) { Printf("makeprocs (%d): ERROR: could not allocate mailbox!", getpid()); Exit(); } if ((mbox_H2 = mbox_create()) == MBOX_FAIL) { Printf("makeprocs (%d): ERROR: could not allocate mailbox!", getpid()); Exit(); } // Open mailbox to prevent deallocation if (mbox_open(mbox_N2) == MBOX_FAIL) { Printf("makeprocs (%d): Could not open mailbox %d!\n", getpid(), mbox_N2); Exit(); } if (mbox_open(mbox_N) == MBOX_FAIL) { Printf("makeprocs (%d): Could not open mailbox %d!\n", getpid(), mbox_N); Exit(); } if (mbox_open(mbox_H2O) == MBOX_FAIL) { Printf("makeprocs (%d): Could not open mailbox %d!\n", getpid(), mbox_H2O); Exit(); } if (mbox_open(mbox_H2) == MBOX_FAIL) { Printf("makeprocs (%d): Could not open mailbox %d!\n", getpid(), mbox_H2); Exit(); } if (mbox_open(mbox_O2) == MBOX_FAIL) { Printf("makeprocs (%d): Could not open mailbox %d!\n", getpid(), mbox_O2); Exit(); } if (mbox_open(mbox_NO2) == MBOX_FAIL) { Printf("makeprocs (%d): Could not open mailbox %d!\n", getpid(), mbox_NO2); Exit(); } // Put some values in the mc structure to send as a message mc.numprocs = numprocs; mc.really_important_char = 'A'; // Create semaphore to not exit this process until all other processes // have signalled that they are complete. To do this, we will initialize // the semaphore to (-1) * (number of signals), where "number of signals" // should be equal to the number of processes we're spawning - 1. Once // each of the processes has signaled, the semaphore should be back to // zero and the final sem_wait below will return. if ((s_procs_completed = sem_create(-(numprocs-1))) == SYNC_FAIL) { Printf("makeprocs (%d): Bad sem_create\n", getpid()); Exit(); } // Setup the command-line arguments for the new process. We're going to // pass the handles to the shared memory page and the semaphore as strings // on the command line, so we must first convert them from ints to strings. ditoa(mbox_N2, mbox_N2_str); ditoa(mbox_H2O, mbox_H2O_str); ditoa(mbox_N, mbox_N_str); ditoa(mbox_H2, mbox_H2_str); ditoa(mbox_O2, mbox_O2_str); ditoa(mbox_NO2, mbox_NO2_str); ditoa(s_procs_completed, s_procs_completed_str); // Now we can create the processes. Note that you MUST end your call to // process_create with a NULL argument so that the operating system // knows how many arguments you are sending. for(i=0; i<num_N2; i++) { process_create(FILENAME_TO_RUN_0, 0, 0, mbox_N2_str,s_procs_completed_str, NULL); // Printf("makeprocs (%d): Process %d created\n", getpid(), i); } for(i=0; i<num_H2O; i++) { process_create(FILENAME_TO_RUN_1, 0, 0, mbox_H2O_str, s_procs_completed_str, NULL); // Printf("makeprocs (%d): Process %d created\n", getpid(), i); } for(i=0; i<num_N2_2N; i++) { process_create(FILENAME_TO_RUN_2, 0, 0, mbox_N2_str,mbox_N_str, s_procs_completed_str, NULL); // Printf("makeprocs (%d): Process %d created\n", getpid(), i); } for(i=0; i<num_H2O_H2_O2; i++) { process_create(FILENAME_TO_RUN_3, 0, 0, mbox_H2O_str,mbox_H2_str,mbox_O2_str, s_procs_completed_str, NULL); // Printf("makeprocs (%d): Process %d created\n", getpid(), i); } for(i=0; i<num_N_O2_NO2; i++) { process_create(FILENAME_TO_RUN_4, 0, 0, mbox_N_str,mbox_O2_str,mbox_NO2_str, s_procs_completed_str, NULL); // Printf("makeprocs (%d): Process %d created\n", getpid(), i); } // And finally, wait until all spawned processes have finished. if (sem_wait(s_procs_completed) != SYNC_SUCCESS) { Printf("Bad semaphore s_procs_completed (%d) in ", s_procs_completed); Printf(argv[0]); Printf("\n"); Exit(); } if (mbox_close(mbox_N2) == MBOX_FAIL) { Printf("makeprocs (%d): Could not close mailbox %d!\n", getpid(), mbox_N2); Exit(); } if (mbox_close(mbox_N) == MBOX_FAIL) { Printf("makeprocs (%d): Could not close mailbox %d!\n", getpid(), mbox_N); Exit(); } if (mbox_close(mbox_O2) == MBOX_FAIL) { Printf("makeprocs (%d): Could not close mailbox %d!\n", getpid(), mbox_O2); Exit(); } if (mbox_close(mbox_NO2) == MBOX_FAIL) { Printf("makeprocs (%d): Could not close mailbox %d!\n", getpid(), mbox_NO2); Exit(); } if (mbox_close(mbox_H2O) == MBOX_FAIL) { Printf("makeprocs (%d): Could not close mailbox %d!\n", getpid(), mbox_H2O); Exit(); } if (mbox_close(mbox_H2) == MBOX_FAIL) { Printf("makeprocs (%d): Could not close mailbox %d!\n", getpid(), mbox_H2); Exit(); } Printf("makeprocs (%d): All other processes completed, exiting main process.\n", getpid()); }
void int_evt_key(void* evt) { key_state_t key_state = *(key_state_t*)evt; FMENU_item_flash_t* current_menu_entry = FMENU_GetCurrentItem(&MENU_menuHandle); FMENU_item_flash_t* new_menu_entry = current_menu_entry; menu_action_t menu_action = MENU_ACTION_ENTER; int int_temp; static uint8_t file_name[SFS_MAX_FILENAME_BUFFER_SIZE]; unsigned char search_string[SFS_MAX_FILENAME_BUFFER_SIZE]; lcd_config_t config; static key_state_t auto_key_state; static bool auto_key_wait = true; static bool auto_key_registered = false; static asy_tmr_t auto_key_timer = ASY_TMR_NO_TIMER; // Navigate to next avrraven.status.state switch (key_state){ case KEY_UP: switch (avrraven.status.state) { case STATE_IDLE: new_menu_entry = FMENU_NavigateUp(&MENU_menuHandle); break; case STATE_CONFIG_DEBUG_ENABLE: lcd_puts_P("ENABLE"); avrraven.user_config.debug_enable = true; break; case STATE_CONFIG_TXTPREV_ENABLE: lcd_puts_P("ENABLE"); avrraven.user_config.txtmsg_preview = true; break; case STATE_CONFIG_FW_UPGRADE: lcd_puts_P("AUTO"); avrraven.user_config.fw_upgr_auto = true; break; case STATE_CONFIG_CONNECT: lcd_puts_P("AUTO"); avrraven.user_config.join_auto = true; break; case STATE_CONFIG_IMG_RCV: lcd_puts_P("AUTO"); avrraven.user_config.fw_rcv_auto = true; break; case STATE_CONFIG_NAME: case STATE_MAIL_COMPOSE: txtedit_event(TXTEDIT_KEY_UP); break; case STATE_CONFIG_LCD_CONTRAST: lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_UP), LCD_NUM_PADDING_SPACE); config = lcd_config_get(); config.contrast = numedit_buffer; lcd_config_set(config); break; case STATE_CONFIG_CLOCK_MIN: { timendate_clk_t set_time; timndate_clock_get(&set_time, avrraven.user_config.unit.clock); // hours from current clock int clk = set_time.hour*100 + numedit_event(NUMEDIT_KEY_UP); // minutes from current editing lcd_num_putdec(clk, LCD_NUM_PADDING_ZERO); } break; case STATE_CONFIG_CLOCK_HOUR: { timendate_clk_t set_time; timndate_clock_get(&set_time, avrraven.user_config.unit.clock); // minutes from current clock int clk = numedit_event(NUMEDIT_KEY_UP)*100 + set_time.min; // hours from current editing lcd_num_putdec(clk, LCD_NUM_PADDING_ZERO); } break; case STATE_CONFIG_LCD_SCROLLING: lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_UP), LCD_NUM_PADDING_SPACE); // Update LCD scrolling settings config = lcd_config_get(); config.scrolling = (lcd_scrolling_t)numedit_value_get(); lcd_config_set(config); break; case STATE_CONFIG_RADIO_CHANNEL: lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_UP), LCD_NUM_PADDING_SPACE); break; case STATE_CONFIG_RADIO_PANID: case STATE_MAIL_COMPOSE_ADDRESS_SET: lcd_num_puthex(numedit_event(NUMEDIT_KEY_UP), LCD_NUM_PADDING_ZERO); break; case STATE_CONFIG_UNIT_TEMP: avrraven.user_config.unit.temp = TEMP_UNIT_CELCIUS; lcd_symbol_clr(LCD_SYMBOL_F); lcd_symbol_set(LCD_SYMBOL_C); break; case STATE_CONFIG_UNIT_CLOCK: avrraven.user_config.unit.clock = TIME_CLOCK_UNIT_24; if (avrraven.user_config.unit.clock == TIME_CLOCK_UNIT_24) { lcd_symbol_clr(LCD_SYMBOL_AM); lcd_symbol_clr(LCD_SYMBOL_PM); lcd_num_puthex(0x2400, LCD_NUM_PADDING_ZERO); } else { lcd_symbol_set(LCD_SYMBOL_AM); lcd_symbol_set(LCD_SYMBOL_PM); lcd_num_puthex(0x1200, LCD_NUM_PADDING_ZERO); } break; case STATE_MAIL_READ: mbox_mail_get(¤t_mail, MBOX_GET_NEXT); if (current_mail != NULL) { int_temp = current_mail->size; lcd_puta(current_mail->data, int_temp); lcd_num_puthex(current_mail->address, LCD_NUM_PADDING_ZERO); } break; case STATE_FW_WAIT_USER_CONFIRMATION: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_AUDIO_FILE_SELECT: strncpy_P((char*)search_string, AUDIO_FILE_TYPE, AUDIO_FILE_TYPE_SIZE); if (avrraven.status.batt_low == false) { sfs_fget(search_string, file_name, SFS_FGET_REV); lcd_puts((const char*)file_name); } else { lcd_puts_P("ERROR"); } break; case STATE_STORAGE_FILE_LIST: strncpy_P((char*)search_string, "*.*", 4); if (avrraven.status.batt_low == false) { sfs_fget(search_string, file_name, SFS_FGET_REV); lcd_puts((const char*)file_name); } else { lcd_puts_P("ERROR"); } break; default: // Key events in unknown state is ignored break; } break; case KEY_DOWN: switch (avrraven.status.state) { case STATE_IDLE: new_menu_entry = FMENU_NavigateDown(&MENU_menuHandle); break; case STATE_CONFIG_DEBUG_ENABLE: lcd_puts_P("DISABLE"); avrraven.user_config.debug_enable = false; break; case STATE_CONFIG_TXTPREV_ENABLE: lcd_puts_P("DISABLE"); avrraven.user_config.txtmsg_preview = false; break; case STATE_CONFIG_FW_UPGRADE: lcd_puts_P("USR ACK"); avrraven.user_config.fw_rcv_auto = false; break; case STATE_CONFIG_CONNECT: lcd_puts_P("MANUAL"); avrraven.user_config.join_auto = false; break; case STATE_CONFIG_IMG_RCV: lcd_puts_P("USR ACK"); avrraven.user_config.fw_rcv_auto = false; break; case STATE_MAIL_COMPOSE: case STATE_CONFIG_NAME: txtedit_event(TXTEDIT_KEY_DOWN); break; case STATE_CONFIG_LCD_CONTRAST: lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_DOWN), LCD_NUM_PADDING_SPACE); config = lcd_config_get(); config.contrast = numedit_buffer; lcd_config_set(config); break; case STATE_CONFIG_CLOCK_MIN: { timendate_clk_t set_time; timndate_clock_get(&set_time, avrraven.user_config.unit.clock); // hours from current clock int clk = set_time.hour*100 + numedit_event(NUMEDIT_KEY_DOWN); // minutes from current editing lcd_num_putdec(clk, LCD_NUM_PADDING_ZERO); } break; case STATE_CONFIG_CLOCK_HOUR: { timendate_clk_t set_time; timndate_clock_get(&set_time, avrraven.user_config.unit.clock); // minutes from current clock int clk = numedit_event(NUMEDIT_KEY_DOWN)*100 + set_time.min; // hours from current editing lcd_num_putdec(clk, LCD_NUM_PADDING_ZERO); } break; case STATE_CONFIG_LCD_SCROLLING: lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_DOWN), LCD_NUM_PADDING_SPACE); // Update LCD scrolling settings config = lcd_config_get(); config.scrolling = (lcd_scrolling_t)numedit_value_get(); lcd_config_set(config); break; case STATE_CONFIG_RADIO_CHANNEL: lcd_num_putdec((int)numedit_event(NUMEDIT_KEY_DOWN), LCD_NUM_PADDING_SPACE); break; case STATE_CONFIG_RADIO_PANID: case STATE_MAIL_COMPOSE_ADDRESS_SET: lcd_num_puthex(numedit_event(NUMEDIT_KEY_DOWN), LCD_NUM_PADDING_ZERO); break; case STATE_CONFIG_UNIT_TEMP: avrraven.user_config.unit.temp = TEMP_UNIT_FAHRENHEIT; lcd_symbol_clr(LCD_SYMBOL_C); lcd_symbol_set(LCD_SYMBOL_F); break; case STATE_CONFIG_UNIT_CLOCK: avrraven.user_config.unit.clock = TIME_CLOCK_UNIT_12; if (avrraven.user_config.unit.clock == TIME_CLOCK_UNIT_24) { lcd_symbol_clr(LCD_SYMBOL_AM); lcd_symbol_clr(LCD_SYMBOL_PM); lcd_num_puthex(0x2400, LCD_NUM_PADDING_ZERO); } else { lcd_symbol_set(LCD_SYMBOL_AM); lcd_symbol_set(LCD_SYMBOL_PM); lcd_num_puthex(0x1200, LCD_NUM_PADDING_ZERO); } break; case STATE_MAIL_READ: mbox_mail_get(¤t_mail, MBOX_GET_PREV); if (current_mail != NULL) { int_temp = current_mail->size; lcd_puta(current_mail->data, int_temp); lcd_num_puthex(current_mail->address, LCD_NUM_PADDING_ZERO); } break; case STATE_FW_WAIT_USER_CONFIRMATION: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_AUDIO_FILE_SELECT: strncpy_P((char*)search_string, AUDIO_FILE_TYPE, AUDIO_FILE_TYPE_SIZE); if (avrraven.status.batt_low == false) { sfs_fget(search_string, file_name, SFS_FGET_FWD); lcd_puts((const char*)file_name); } else { lcd_puts_P("ERROR"); } break; case STATE_STORAGE_FILE_LIST: strncpy_P((char*)search_string, "*.*", 4); if (avrraven.status.batt_low == false) { sfs_fget(search_string, file_name, SFS_FGET_FWD); lcd_puts((const char*)file_name); } else { lcd_puts_P("ERROR"); } break; default: // Key events in unknown state is ignored break; } break; case KEY_LEFT: switch (avrraven.status.state) { case STATE_IDLE: new_menu_entry = FMENU_NavigateLeft(&MENU_menuHandle); break; case STATE_CONFIG_CLOCK_MIN: { // Set min timendate_clk_t new_time; timndate_clock_get(&new_time, avrraven.user_config.unit.clock); new_time.min = numedit_buffer; new_time.sec = 0; timndate_clock_set(new_time, avrraven.user_config.unit.clock); } // Done numeric editing on hours numedit_done(); // Start numeric editor on hours { timendate_clk_t current_time; timndate_clock_get(¤t_time, avrraven.user_config.unit.clock); numedit_buffer = current_time.hour; numedit_config_t conf = { .number = &numedit_buffer, .min_value = 0, .max_value = 23, .radix = NUMEDIT_RADIX_DEC, .size = 2, .offset = 2 }; numedit_init(conf); } avrraven.status.state = STATE_CONFIG_CLOCK_HOUR; break; case STATE_AUDIO_FILE_SELECT: if (audio_playback_active() == true) { audio_playback_stop(); } lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_NAME: case STATE_MAIL_COMPOSE: txtedit_event(TXTEDIT_KEY_LEFT); break; case STATE_CONFIG_RADIO_PANID: case STATE_MAIL_COMPOSE_ADDRESS_SET: lcd_num_puthex(numedit_event(NUMEDIT_KEY_LEFT), LCD_NUM_PADDING_ZERO); break; case STATE_CONFIG_UNIT_TEMP: break; case STATE_CONFIG_UNIT_CLOCK: break; /* case STATE_MAIL_READ: mbox_mail_getnext(&txtmsg); if (txtmsg != NULL) { int_temp = ((txtmsg->size) < LCD_SEGMENT_COUNT) ? txtmsg->size : LCD_SEGMENT_COUNT; mail_read_offset = ((mail_read_offset + LCD_SEGMENT_COUNT) >= txtmsg->size) ? mail_read_offset : (mail_read_offset + LCD_SEGMENT_COUNT); lcd_puta(&txtmsg->data[mail_read_offset], int_temp); } break;*/ case STATE_FW_WAIT_USER_CONFIRMATION: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; default: // Key events in unknown state is ignored break; } break; case KEY_RIGHT: switch (avrraven.status.state) { case STATE_IDLE: new_menu_entry = FMENU_NavigateRight(&MENU_menuHandle); break; case STATE_CONFIG_CLOCK_HOUR: { // Set hour timendate_clk_t new_time; timndate_clock_get(&new_time, avrraven.user_config.unit.clock); new_time.hour = numedit_buffer; new_time.sec = 0; timndate_clock_set(new_time, avrraven.user_config.unit.clock); } // Done numeric editing on hours numedit_done(); // Start numeric editor on minutes { timendate_clk_t current_time; timndate_clock_get(¤t_time, avrraven.user_config.unit.clock); numedit_buffer = current_time.min; numedit_config_t conf = { .number = &numedit_buffer, .min_value = 0, .max_value = 59, .radix = NUMEDIT_RADIX_DEC, .size = 2, .offset = 0 }; numedit_init(conf); } avrraven.status.state = STATE_CONFIG_CLOCK_MIN; break; case STATE_MAIL_COMPOSE: case STATE_CONFIG_NAME: txtedit_event(TXTEDIT_KEY_RIGHT); break; case STATE_CONFIG_RADIO_PANID: case STATE_MAIL_COMPOSE_ADDRESS_SET: lcd_num_puthex(numedit_event(NUMEDIT_KEY_RIGHT), LCD_NUM_PADDING_ZERO); break; case STATE_CONFIG_UNIT_TEMP: break; case STATE_CONFIG_UNIT_CLOCK: break; case STATE_FW_WAIT_USER_CONFIRMATION: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; default: // Key events in unknown state is ignored break; } break; case KEY_ENTER: switch (avrraven.status.state) { case STATE_DISPLAY_MESSAGE: // Default display avrraven.status.state lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); led_status_set(LED_OFF); lcd_num_clr_all(); // Refresh menu function (in case it affects the display) menu_action = MENU_ACTION_REFRESH; if (current_menu_entry->action != NULL) { current_menu_entry->action((void*)&menu_action); } avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_LCD_CONTRAST: // Done numeric editing, write value to user configuration numedit_done(); avrraven.user_config.lcd.contrast = (lcd_contrast_t)numedit_buffer; // Update LCD HW config = lcd_config_get(); config.contrast = avrraven.user_config.lcd.contrast; lcd_config_set(config); // Write new user configuration to EEPROM USER_CONFIG_STORE(); // Refresh menu title lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_LCD_SCROLLING: // Done numeric editing, write value to user configuration avrraven.user_config.lcd.scrolling = (lcd_scrolling_t)numedit_value_get(); numedit_done(); // Update LCD scrolling settings config = lcd_config_get(); config.scrolling = avrraven.user_config.lcd.scrolling; lcd_config_set(config); // Write new user configuration to EEPROM USER_CONFIG_STORE(); // Refresh menu title lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_RADIO_CHANNEL: // Done numeric editing, write value to user configuration avrraven.user_config.channel = numedit_value_get(); numedit_done(); // Write new user configuration to EEPROM USER_CONFIG_STORE(); // Refresh menu title lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_CLOCK_HOUR: { // Set hour timendate_clk_t new_time; timndate_clock_get(&new_time, avrraven.user_config.unit.clock); new_time.hour = numedit_value_get(); new_time.sec = 0; timndate_clock_set(new_time, avrraven.user_config.unit.clock); } // Done numeric editing on hours numedit_done(); // Start show clock event menu_action = MENU_ACTION_REFRESH; if (current_menu_entry->action != NULL) { current_menu_entry->action((void*)&menu_action); } avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_CLOCK_MIN: { // Set min timendate_clk_t new_time; timndate_clock_get(&new_time, avrraven.user_config.unit.clock); new_time.min = numedit_value_get(); new_time.sec = 0; timndate_clock_set(new_time, avrraven.user_config.unit.clock); } // Done numeric editing on minutes numedit_done(); // Start show clock event menu_action = MENU_ACTION_REFRESH; if (current_menu_entry->action != NULL) { current_menu_entry->action((void*)&menu_action); } avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_DEBUG_ENABLE: // Write new user configuration to EEPROM USER_CONFIG_STORE(); // Refresh menu title lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_RADIO_PANID: // Done numeric editing on hours numedit_done(); // Write new user configuration to EEPROM USER_CONFIG_STORE(); // Refresh menu title lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_UNIT_TEMP: case STATE_CONFIG_UNIT_CLOCK: case STATE_CONFIG_TXTPREV_ENABLE: case STATE_CONFIG_FW_UPGRADE: case STATE_CONFIG_CONNECT: case STATE_CONFIG_IMG_RCV: // Write new user configuration to EEPROM USER_CONFIG_STORE(); // Refresh menu title lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_MAIL_PREVIEW: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); menu_action = MENU_ACTION_REFRESH; if (current_menu_entry->action != NULL) { current_menu_entry->action((void*)&menu_action); } led_status_set(LED_OFF); avrraven.status.state = STATE_IDLE; break; case STATE_AUDIO_FILE_SELECT: if (audio_playback_active() == false) { audio_playback_start(file_name, false); } else { audio_playback_stop(); } break; case STATE_STORAGE_FILE_LIST: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_FW_WAIT_USER_CONFIRMATION: avrraven.status.state = STATE_FW_WRITE_INIT; break; case STATE_IDLE: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); if (current_menu_entry->action != NULL) { current_menu_entry->action((void*)&menu_action); } break; case STATE_AUDIO_RECORD: audio_record_stop(); lcd_symbol_clr(LCD_SYMBOL_MIC); avrraven.status.state = STATE_IDLE; break; case STATE_CONFIG_NAME: txtedit_event(TXTEDIT_KEY_ENTER); txtedit_done(); USER_CONFIG_STORE(); // Print the menu title to the display lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); avrraven.status.state = STATE_IDLE; break; case STATE_MAIL_READ: lcd_puts_P((PROGMEM_DECLARE(const char)*)FMENU_GetTitle(current_menu_entry)); // If any unread mail, show closed envelope if (mbox_unread() == true) { lcd_symbol_set(LCD_SYMBOL_ENV_MAIN); lcd_symbol_set(LCD_SYMBOL_ENV_CL); lcd_symbol_clr(LCD_SYMBOL_ENV_OP); // If all mail read, show open envelope } else { lcd_symbol_set(LCD_SYMBOL_ENV_MAIN); lcd_symbol_set(LCD_SYMBOL_ENV_CL); lcd_symbol_set(LCD_SYMBOL_ENV_OP); } // show number of mails on display int_temp = mbox_mail_count_get(); lcd_num_putdec(int_temp, LCD_NUM_PADDING_SPACE); mbox_close(); avrraven.status.state = STATE_IDLE; break; case STATE_MAIL_COMPOSE: txtedit_event(TXTEDIT_KEY_ENTER); txtedit_done(); mbox_mail_buffer_put(new_mail_buffer); { lcd_puts_P("ADDRESS"); numedit_config_t conf = { .number = &numedit_buffer, .min_value = 0, .max_value = UINT16_MAX, .radix = NUMEDIT_RADIX_DEC, .size = 1, .offset = 0 }; numedit_init(conf); } numedit_buffer = 0x0000; // default address lcd_num_puthex(numedit_buffer, LCD_NUM_PADDING_ZERO); avrraven.status.state = STATE_MAIL_COMPOSE_ADDRESS_SET; break; case STATE_MAIL_COMPOSE_ADDRESS_SET: avrraven.status.trans_seq_nmbr = mbox_mail_send(numedit_value_get(), txtedit_size_get()); avrraven.status.state = STATE_MAIL_SEND_INIT; numedit_done(); mbox_close(); break; default: lcd_puts_P("CANCELED"); led_status_set(LED_FAST_BLINK); lcd_num_clr_all(); avrraven.status.state = STATE_DISPLAY_MESSAGE; break; } break; case KEY_NO_KEY: // Do nothing? break; default: // Key events in unknown state is ignored break; } // Navigate menu if new menu entry is different from last if (new_menu_entry != current_menu_entry) { navigate_menu(current_menu_entry, new_menu_entry, menu_action); } // After processing the key event it is safe to enable auto key auto_key_state = key_state; if (key_state != KEY_NO_KEY) { if (auto_key_registered == false) { long delay; if (auto_key_wait == true) { delay = 300; auto_key_wait = false; } else { asy_tmr_put(auto_key_timer); delay = 80; auto_key_registered = true; } auto_key_timer = asy_tmr_get(int_evt_key, (void*)&auto_key_state, delay); } } else { asy_tmr_put(auto_key_timer); auto_key_wait = true; auto_key_registered = false; } } void int_evt_check_key(void* evt) { static bool first_time = true; // Static variable used as flag to indicate first execution of function static key_state_t last_key_state; // Variable hodling last value of the joystick. Used to detect changes in joystick state /* Check joystick state. Post event if any change since last * First time function is executed no event is posted. This is * done to not respond if joystick activated while booting */ key_state_t new_key_state; if (first_time) { last_key_state = key_state_get(); new_key_state = last_key_state; first_time = false; } else if((new_key_state = key_state_get()) != last_key_state){ last_key_state = new_key_state; vrt_post_event(int_evt_key, (void*)&last_key_state); } } void int_evt_lcd_shift_left(void* evt) { lcd_text_shift_left(); } void int_evt_lcd_cursor_toggle(void* evt) { lcd_cursor_toggle(); } void int_evt_lcd_num_refresh(void* evt) { lcd_num_refresh(); } void int_evt_update_batt(void* evt) { int16_t vcc_batt = battery_voltage_read(); lcd_symbol_battery_empty(); if (vcc_batt>2000) { lcd_symbol_set(LCD_SYMBOL_BAT_CAP1); } if (vcc_batt>2500) { lcd_symbol_set(LCD_SYMBOL_BAT_CAP2); } if (vcc_batt>2800) { lcd_symbol_set(LCD_SYMBOL_BAT_CAP3); } // Indicate low battery if voltage less than 2.6 V if (avrraven.status.batt_low == false) { if (vcc_batt<2600) { avrraven.status.batt_low = true; lcd_symbol_set(LCD_SYMBOL_ATT); mbox_deinit(); sfs_deinit(); } } } void int_evt_show_clock(void* evt) { static bool col = false; timendate_clk_t clk; timndate_clock_get(&clk, avrraven.user_config.unit.clock); int16_t display_clock = clk.hour*100 + clk.min; lcd_num_putdec(display_clock, LCD_NUM_PADDING_ZERO); if ((col = !col) == true){ lcd_symbol_set(LCD_SYMBOL_COL); } else { lcd_symbol_clr(LCD_SYMBOL_COL); } } void int_evt_toggle_num_digit(void* evt) { int8_t digit_mask = *(int8_t*)evt; lcd_num_enable(digit_mask); } void int_evt_audio(void* evt) { audio_event_handler(); }
int main(int argc, char *argv[]) { int mb = mbox_open(); /* Enable QPU for execution */ int qpu_enabled = !qpu_enable(mb, 1); if (!qpu_enabled) { printf("Unable to enable QPU. Check your firmware is latest."); goto cleanup; } /* Allocate GPU memory and map it into ARM address space */ unsigned size = 4096; unsigned align = 4096; unsigned handle = mem_alloc(mb, size, align, GPU_MEM_FLG); if (!handle) { printf("Failed to allocate GPU memory."); goto cleanup; } void *gpu_pointer = (void *)mem_lock(mb, handle); void *arm_pointer = mapmem((unsigned)gpu_pointer+GPU_MEM_MAP, size); unsigned *p = (unsigned *)arm_pointer; /* +---------------+ <----+ | QPU Code | | | ... | | +---------------+ <--+ | | Uniforms | | | +---------------+ | | | QPU0 Uniform -----+ | | QPU0 Start -------+ | ... | | QPUn Uniform | | QPUn PC -------+ +---------------+ */ /* Copy QPU program into GPU memory */ unsigned *qpu_code = p; memcpy(p, program, sizeof program); p += (sizeof program)/(sizeof program[0]); /* Build Uniforms */ unsigned *qpu_uniform = p; *p++ = 1; /* Build QPU Launch messages */ unsigned *qpu_msg = p; *p++ = as_gpu_address(qpu_uniform); *p++ = as_gpu_address(qpu_code); int i; for (i=0; i<16+1+2; i++) { printf("%08x: %08x\n", gpu_pointer+i*4, ((unsigned *)arm_pointer)[i]); } printf("qpu exec %08x\n", gpu_pointer + ((void *)qpu_msg - arm_pointer)); /* Launch QPU program and block till its done */ unsigned r = execute_qpu(mb, GPU_QPUS, as_gpu_address(qpu_msg), 1, 10000); printf("%d\n", r); cleanup: /* Release GPU memory */ if (arm_pointer) { unmapmem(arm_pointer, size); } if (handle) { mem_unlock(mb, handle); mem_free(mb, handle); } /* Release QPU */ if (qpu_enabled) { qpu_enable(mb, 0); } /* Release mailbox */ mbox_close(mb); }
void main (int argc, char *argv[]) { char h2_buffer[H2_SIZE]; char o2_buffer[O2_SIZE]; char so2_buffer[SO2_SIZE]; char h2so4_molecule[H2SO4_SIZE] = {'H', '2', 'S', 'O', '4'}; mbox_t h_mbox_h2; mbox_t h_mbox_o2; mbox_t h_mbox_so2; mbox_t h_mbox_h2so4; sem_t s_procs_completed; // Semaphore to signal the original process that we're done /* int ct; */ /* Printf("argc = %d\n", argc); */ /* for(ct = 0 ; ct < argc; ct++){ */ /* Printf("argv[%d] = %s\n", ct, argv[ct]); */ /* } */ if (argc != 6) { Printf("Usage: %s <mailbox h2> <mailbox o2> <mailbox so2> <mailbox h2so4> <handle_to_page_mapped_semaphore>\n"); Exit(); } // Convert the command-line strings into integers for use as handles h_mbox_h2 = dstrtol(argv[1], NULL, 10); // The "10" means base 10 h_mbox_o2 = dstrtol(argv[2], NULL, 10); // The "10" means base 10 h_mbox_so2 = dstrtol(argv[3], NULL, 10); // The "10" means base 10 h_mbox_h2so4 = dstrtol(argv[4], NULL, 10); // The "10" means base 10 s_procs_completed = dstrtol(argv[5], NULL, 10); // Open the h2 mailbox if (mbox_open(h_mbox_h2) == MBOX_FAIL) { Printf("Reaction 3 (%d): Could not open the so4 mailbox!\n", getpid()); Exit(); } // Wait for the h2 molecule from the mailbox if (mbox_recv(h_mbox_h2, H2_SIZE, (void *) h2_buffer) == MBOX_FAIL) { Printf("Reaction 3 (%d): Could not receive message from the mbox %d!\n", getpid(), h_mbox_h2); Exit(); } // Close the h2 mailbox if (mbox_close(h_mbox_h2) == MBOX_FAIL) { Printf("Reaction 3 (%d): Could not close the mailbox!\n", getpid()); Exit(); } // Open the o2 mailbox if (mbox_open(h_mbox_o2) == MBOX_FAIL) { Printf("Reaction 3 (%d): Could not open the o2 mailbox!\n", getpid()); Exit(); } // Send the o2 to the o2 mailbox if (mbox_recv(h_mbox_o2, O2_SIZE, (void *) o2_buffer) == MBOX_FAIL) { Printf("Reaction 3 (%d): Could not send message to the mbox %d!\n", getpid(), h_mbox_o2); Exit(); } // Close the o2 mailbox if (mbox_close(h_mbox_o2) == MBOX_FAIL) { Printf("Reaction 3 (%d): Could not close the mailbox!\n", getpid()); Exit(); } // Open the SO2 mailbox if (mbox_open(h_mbox_so2) == MBOX_FAIL) { Printf("Reaction 3 (%d): Could not open the so2 mailbox!\n", getpid()); Exit(); } // Send the SO2 to the SO2 mailbox if (mbox_recv(h_mbox_so2, SO2_SIZE, (void *) so2_buffer) == MBOX_FAIL) { Printf("Reaction 3 (%d): Could not send message to the mbox %d!\n", getpid(), h_mbox_so2); Exit(); } // Close the SO2 mailbox if (mbox_close(h_mbox_so2) == MBOX_FAIL) { Printf("Reaction 2 (%d): Could not close the mailbox!\n", getpid()); Exit(); } // Open the h2so4 mailbox if (mbox_open(h_mbox_h2so4) == MBOX_FAIL) { Printf("Reaction 3 (%d): Could not open the h2so4 mailbox!\n", getpid()); Exit(); } // Send the h2so4 to the o2 mailbox if (mbox_send(h_mbox_h2so4, H2SO4_SIZE, (void *) h2so4_molecule) == MBOX_FAIL) { Printf("Reaction 3 (%d): Could not send message to the mbox %d!\n", getpid(), h_mbox_h2so4); Exit(); } // Close the h2so4 mailbox if (mbox_close(h_mbox_h2so4) == MBOX_FAIL) { Printf("Reaction 3 (%d): Could not close the mailbox!\n", getpid()); Exit(); } // Now print a message to show that everything worked Printf("A molecule H2SO4 has been generated\n"); // Signal the semaphore to tell the original process that we're done if(sem_signal(s_procs_completed) != SYNC_SUCCESS) { Printf("Reaction 3 (%d): Bad semaphore s_procs_completed (%d)!\n", getpid(), s_procs_completed); Exit(); } Printf("Reaction 3 (%d): Done!\n", getpid()); }