static int ppm_getuint(int fd) { int ch; int i; int digitVal; do { ch = ppm_getc(fd); } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); if (ch == PLUGIN_ERROR) return PLUGIN_ERROR; if (ch < '0' || ch > '9') { ppm_error("Junk (%c) in file where an integer should be.", ch); return PLUGIN_ERROR; } i = 0; do { digitVal = ch - '0'; if (i > INT_MAX/10 - digitVal) { ppm_error("ASCII decimal integer in file is "\ "too large to be processed."); return PLUGIN_ERROR; } i = i * 10 + digitVal; ch = ppm_getc(fd); } while (ch >= '0' && ch <= '9'); if (ch == PLUGIN_ERROR) return PLUGIN_ERROR; return i; }
int read_ppm_init_rest(int fd, int * const cols, int * const rows, int * const maxval) { /* Read size. */ *cols = ppm_getuint(fd); *rows = ppm_getuint(fd); if ((long unsigned int)(*cols * *rows) > PPM_MAXSIZE) { ppm_error("Imagesize (%ld pixels) is too large. "\ "The maximum allowed is %ld.", (long unsigned int)(*cols * *rows), (long unsigned int)PPM_MAXSIZE); return PLUGIN_ERROR; } /* Read maxval. */ *maxval = ppm_getuint(fd); if (*maxval > PPM_OVERALLMAXVAL) { ppm_error("maxval of input image (%u) is too large. "\ "The maximum allowed by the PPM is %u.", *maxval, PPM_OVERALLMAXVAL); return PLUGIN_ERROR; } if (*maxval == 0) { ppm_error("maxval of input image is zero."); return PLUGIN_ERROR; } return 1; }
/* Read from the file header dimensions as well as max * int value used */ static int read_ppm_init_rest(int fd, struct ppm_info *ppm) { /* Read size. */ ppm->x = ppm_getuint(fd); ppm->y = ppm_getuint(fd); #ifdef HAVE_LCD_COLOR ppm->native_img_size = ppm->x * ppm->y * FB_DATA_SZ; #endif if (ppm->native_img_size > ppm->buf_size) { return PLUGIN_OUTOFMEM; } /* Read maxval. */ ppm->maxval = ppm_getuint(fd); if (ppm->maxval > PPM_OVERALLMAXVAL) { ppm_error("maxval of input image (%u) is too large. "\ "The maximum allowed by the PPM is %u.", ppm->maxval, PPM_OVERALLMAXVAL); return PLUGIN_ERROR; } if (ppm->maxval == 0) { ppm_error("maxval of input image is zero."); return PLUGIN_ERROR; } return PLUGIN_OK; }
/* ppm_pulprog_recv: receives a new pulse program from the host. */ void ppm_pulprog_recv (void) { /* declare variables to hold read bytes. */ int16_t b0, b1; /* read the pulse program length. */ b0 = usb_cdc_getchar (); b1 = usb_cdc_getchar (); /* check for any errors. */ if (b0 == -1 || b1 == -1) { /* return failure. */ ppm_error (); return; } /* set the number of pulse program bytes. */ n_pulprog = WORD (b0, b1); /* loop through the pulse program array bytes. */ for (i_pulprog = 0; i_pulprog < n_pulprog && i_pulprog < SZ_PULPROG; i_pulprog++) { /* read the next byte. */ b0 = usb_cdc_getchar (); /* check if the byte is valid. */ if (b0 != -1) { /* store the pulse program byte in the array. */ pulprog[i_pulprog] = LSB (b0); } else { /* return failure. */ ppm_error (); return; } } /* loop from the end of the received data to the end of the array. */ for (i_pulprog = n_pulprog; i_pulprog < SZ_PULPROG; i_pulprog++) { /* zero the currently indexed byte. */ pulprog[i_pulprog] = 0x00; } /* zero the pulse program index. */ i_pulprog = 0; /* send an acknowledgement that the pulse program was set. */ ppm_done (); }
static int read_ppm_row(int fd, struct ppm_info *ppm, int row) { int col; int r, g, b; #ifdef HAVE_LCD_COLOR #if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE fb_data *dst = (fb_data *) ppm->buf + row; const int stride = ppm->x; #else fb_data *dst = (fb_data *) ppm->buf + ppm->x*row; const int stride = 1; #endif #endif /* HAVE_LCD_COLOR */ switch (ppm->format) { case PPM_FORMAT: for (col = 0; col < ppm->x; ++col) { r = ppm_getuint(fd); g = ppm_getuint(fd); b = ppm_getuint(fd); if (r == PLUGIN_ERROR || g == PLUGIN_ERROR || b == PLUGIN_ERROR) { return PLUGIN_ERROR; } *dst = FB_RGBPACK( (255 * r)/ppm->maxval, (255 * g)/ppm->maxval, (255 * b)/ppm->maxval); dst += stride; } break; case RPPM_FORMAT: for (col = 0; col < ppm->x; ++col) { r = ppm_getrawsample(fd, ppm->maxval); g = ppm_getrawsample(fd, ppm->maxval); b = ppm_getrawsample(fd, ppm->maxval); if (r == PLUGIN_ERROR || g == PLUGIN_ERROR || b == PLUGIN_ERROR) { return PLUGIN_ERROR; } *dst = FB_RGBPACK( (255 * r)/ppm->maxval, (255 * g)/ppm->maxval, (255 * b)/ppm->maxval); dst += stride; } break; default: ppm_error("What?!"); return PLUGIN_ERROR; } return PLUGIN_OK; }
int read_ppm_row(int fd, int const row, int const cols, int const rows, int const maxval, int const format) { #if !(defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE) (void) rows; #endif int col; int r, g, b; switch (format) { case PPM_FORMAT: for (col = 0; col < cols; ++col) { r = ppm_getuint(fd); g = ppm_getuint(fd); b = ppm_getuint(fd); if (r == PLUGIN_ERROR || g == PLUGIN_ERROR || b == PLUGIN_ERROR) { return PLUGIN_ERROR; } *BUFADDR(col, row, cols, rows) = LCD_RGBPACK( (255 / maxval) * r, (255 / maxval) * g, (255 / maxval) * b); } break; case RPPM_FORMAT: for (col = 0; col < cols; ++col) { r = ppm_getrawsample(fd, maxval); g = ppm_getrawsample(fd, maxval); b = ppm_getrawsample(fd, maxval); if (r == PLUGIN_ERROR || g == PLUGIN_ERROR || b == PLUGIN_ERROR) { return PLUGIN_ERROR; } *BUFADDR(col, row, cols, rows) = LCD_RGBPACK( (255 / maxval) * r, (255 / maxval) * g, (255 / maxval) * b); } break; default: ppm_error("What?!"); return PLUGIN_ERROR; } return 1; }
static int ppm_getc(int fd) { unsigned char ch; if (rb->read(fd, &ch, 1) < 1) { ppm_error("EOF. Read error reading a byte"); return PLUGIN_ERROR; } if (ch == '#') { do { if (rb->read(fd, &ch, 1) < 1) { ppm_error("EOF. Read error reading a byte"); return PLUGIN_ERROR; } } while (ch != '\n' && ch != '\r'); } return (int)ch; }
char ppm_getc(int fd) { char ch; if (!rb->read(fd, &ch, 1)) { ppm_error("EOF. Read error reading a byte"); return PLUGIN_ERROR; } if (ch == '#') { do { if (!rb->read(fd, &ch, 1)) { ppm_error("EOF. Read error reading a byte"); return PLUGIN_ERROR; } } while (ch != '\n' && ch != '\r'); } return ch; }
static int ppm_getrawbyte(int fd) { unsigned char by; if (rb->read(fd, &by, 1) < 1) { ppm_error("EOF. Read error while reading a one-byte sample."); return PLUGIN_ERROR; } return (int)by; }
static int ppm_read_magic_number(int fd) { unsigned char i1, i2; if(rb->read(fd, &i1, 1) < 1 || rb->read(fd, &i2, 1) < 1) { ppm_error( "Error reading magic number from ppm image stream. "\ "Most often, this means your input file is empty." ); return PLUGIN_ERROR; } return i1 * 256 + i2; }
static int ppm_getrawsample(int fd, int const maxval) { if (maxval < 256) { /* The sample is just one byte. Read it. */ return(ppm_getrawbyte(fd)); } else { /* The sample is two bytes. Read both. */ unsigned char byte_pair[2]; if (rb->read(fd, byte_pair, 2) < 2) { ppm_error("EOF. Read error while reading a long sample."); return PLUGIN_ERROR; } return((byte_pair[0]<<8) | byte_pair[1]); } }
static int read_ppm_init(int fd, struct ppm_info *ppm) { /* Check magic number. */ ppm->format = ppm_read_magic_number( fd ); if (ppm->format == PLUGIN_ERROR) return PLUGIN_ERROR; switch (ppm->format) { case PPM_FORMAT: case RPPM_FORMAT: return read_ppm_init_rest(fd, ppm); default: ppm_error( "Bad magic number - not a ppm or rppm file." ); return PLUGIN_ERROR; } return PLUGIN_OK; }
void read_ppm_init(int fd, int * const cols, int * const rows, int * const maxval, int * const format) { /* Check magic number. */ *format = ppm_read_magic_number( fd ); if (*format == PLUGIN_ERROR) return; switch (*format) { case PPM_FORMAT: case RPPM_FORMAT: if(read_ppm_init_rest(fd, cols, rows, maxval) == PLUGIN_ERROR) { *format = PLUGIN_ERROR; } break; default: ppm_error( "Bad magic number - not a ppm or rppm file." ); *format = PLUGIN_ERROR; } }
/* ppm_execute: runs the currently downloaded pulse program. */ void ppm_execute (void) { /* declare required variables. */ uint32_t f32, n32; uint16_t a16, d16; uint8_t a8, en; /* declare the current value of the shim dac output. */ uint16_t dac16 = 0x0000; /* initialize all interpreter variables. */ VAR_INIT (n32); VAR_INIT (f32); VAR_INIT (d16); VAR_INIT (a16); VAR_INIT (a8); VAR_INIT (en); VAR_INIT (dac16); /* loop through the pulse program array. */ for (i_pulprog = 0; i_pulprog < n_pulprog && i_pulprog < SZ_PULPROG; i_pulprog++) { /* determine the pulse program command at the current index. */ switch (pulprog[i_pulprog]) { /* short, imprecise delay. */ #ifdef PPM_PULPROG_HAVE_DEADTIME case PPM_PULPROG_DEADTIME: /* build the delay time word and run the dead time command. */ d16 = WORD (pulprog[i_pulprog + 1], pulprog[i_pulprog + 2]); ppm_deadtime (d16); /* skip to the next pulse program command. */ i_pulprog += 2; break; #endif /* precise delay. */ #ifdef PPM_PULPROG_HAVE_DELAY case PPM_PULPROG_DELAY: /* build the delay time word and run the delay command. */ d16 = WORD (pulprog[i_pulprog + 1], pulprog[i_pulprog + 2]); dac16 = ppm_delay (d16, dac16); /* skip to the next pulse program command. */ i_pulprog += 2; break; #endif /* polarization control. */ #ifdef PPM_PULPROG_HAVE_POLARIZE case PPM_PULPROG_POLARIZE: /* get the enable byte and run the control command. */ en = pulprog[i_pulprog + 1]; ppm_ccs_enable (en); /* skip to the next pulse program command. */ i_pulprog += 1; break; #endif /* relay control. */ #ifdef PPM_PULPROG_HAVE_RELAY case PPM_PULPROG_RELAY: /* get the enable byte and run the control command. */ en = pulprog[i_pulprog + 1]; ppm_relay_enable (en); /* skip to the next pulse program command. */ i_pulprog += 1; break; #endif /* acquisition. */ #ifdef PPM_PULPROG_HAVE_ACQUIRE case PPM_PULPROG_ACQUIRE: /* build the acquisition sample count. */ n32 = WORD32 (pulprog[i_pulprog + 1], pulprog[i_pulprog + 2], pulprog[i_pulprog + 3], pulprog[i_pulprog + 4]); /* build the acquisition sample rate overflow. */ d16 = WORD (pulprog[i_pulprog + 5], pulprog[i_pulprog + 6]); /* run the acquisition command. */ ppm_acquire (n32, d16); /* skip to the next pulse program command. */ i_pulprog += 6; break; #endif /* adiabatic polarization rising edge. */ #ifdef PPM_PULPROG_HAVE_TX case PPM_PULPROG_TXRISE: /* build the sample count word. */ d16 = WORD (pulprog[i_pulprog + 1], pulprog[i_pulprog + 2]); /* build the amplitude step word. */ a16 = WORD (pulprog[i_pulprog + 3], pulprog[i_pulprog + 4]); /* run the rising edge command. */ dac16 = ppm_txrise (d16, a16, dac16); /* skip to the next pulse program command. */ i_pulprog += 4; break; #endif /* adiabatic polarization falling edge. */ #ifdef PPM_PULPROG_HAVE_TX case PPM_PULPROG_TXFALL: /* build the sample count word. */ d16 = WORD (pulprog[i_pulprog + 1], pulprog[i_pulprog + 2]); /* build the amplitude step word. */ a16 = WORD (pulprog[i_pulprog + 3], pulprog[i_pulprog + 4]); /* run the falling edge command. */ dac16 = ppm_txfall (d16, a16, dac16); /* skip to the next pulse program command. */ i_pulprog += 4; break; #endif /* sinusoidal pulse. */ #ifdef PPM_PULPROG_HAVE_TX case PPM_PULPROG_TXPULSE: /* build the synthesis sample count. */ n32 = WORD32 (pulprog[i_pulprog + 1], pulprog[i_pulprog + 2], pulprog[i_pulprog + 3], pulprog[i_pulprog + 4]); /* build the frequency tuning word. */ f32 = WORD32 (pulprog[i_pulprog + 5], pulprog[i_pulprog + 6], pulprog[i_pulprog + 7], pulprog[i_pulprog + 7]); /* get the amplitude multiplier byte. */ a8 = pulprog[i_pulprog + 9]; /* run the pulse synthesis command. */ ppm_txpulse (n32, f32, a8); /* return the transmit coil dac output to zero. */ spi_write_dac_a (0x0000); /* skip to the next pulse program command. */ i_pulprog += 9; break; #endif /* capacitive tuning. */ #ifdef PPM_PULPROG_HAVE_TUNE case PPM_PULPROG_TUNE: /* build the tuning word. */ a16 = WORD (pulprog[i_pulprog + 1], pulprog[i_pulprog + 2]); /* run the tuning command. */ ppm_settune (a16); /* skip to the next pulse program command. */ i_pulprog += 2; break; #endif /* x-axis shim. */ #ifdef PPM_PULPROG_HAVE_SHIM_X case PPM_PULPROG_SHIM_X: /* build the shimming word. */ a16 = WORD (pulprog[i_pulprog + 1], pulprog[i_pulprog + 2]); /* run the shimming command. */ ppm_setshim_x (a16); /* skip to the next pulse program command. */ i_pulprog += 2; break; #endif /* y-axis shim. */ #ifdef PPM_PULPROG_HAVE_SHIM_Y case PPM_PULPROG_SHIM_Y: /* build the shimming word. */ a16 = WORD (pulprog[i_pulprog + 1], pulprog[i_pulprog + 2]); /* run the shimming command. */ ppm_setshim_y (a16); /* skip to the next pulse program command. */ i_pulprog += 2; break; #endif /* z-axis shim. */ #ifdef PPM_PULPROG_HAVE_SHIM_Z case PPM_PULPROG_SHIM_Z: /* build the shimming word. */ a16 = WORD (pulprog[i_pulprog + 1], pulprog[i_pulprog + 2]); /* run the shimming command. */ ppm_setshim_z (a16); /* skip to the next pulse program command. */ i_pulprog += 2; break; #endif /* end execution. */ case PPM_PULPROG_END: /* send back a completion code and end execution. */ ppm_done (); return; /* unrecognized command. */ default: /* send back an error code and end execution. */ ppm_error (); return; } } }
/* this is the plugin entry point */ enum plugin_status plugin_start(const void* parameter) { static char filename[MAX_PATH]; int fd; int cols; int rows; int maxval; int result; struct bitmap small_bitmap, orig_bitmap; if(!parameter) return PLUGIN_ERROR; size_t buffer_size; char *audiobuf = rb->plugin_get_buffer(&buffer_size); if (buffer_size < PPM_MAXSIZE + LCD_WIDTH * LCD_HEIGHT + 1) { /* steal from audiobuffer if plugin buffer is too small */ audiobuf = rb->plugin_get_audio_buffer(&buffer_size); if (buffer_size < PPM_MAXSIZE + LCD_WIDTH * LCD_HEIGHT + 1) { rb->splash(HZ, "Not enough memory"); return PLUGIN_ERROR; } } /* align on 16 bits */ audiobuf = (char *)(((uintptr_t)audiobuf + 1) & ~1); buffer = (fb_data *)audiobuf; lcd_buf = (fb_data*) (audiobuf + PPM_MAXSIZE); rb->strcpy(filename, parameter); fd = rb->open(filename, O_RDONLY); if (fd < 0) { ppm_error("Couldnt open file: %s, %d", filename, fd); return PLUGIN_ERROR; } result = read_ppm(fd, &cols, &rows, &maxval); rb->close(fd); if(result == PLUGIN_ERROR) return PLUGIN_ERROR; orig_bitmap.width = cols; orig_bitmap.height = rows; orig_bitmap.data = (char*)buffer; if (cols > LCD_WIDTH || rows > LCD_HEIGHT) { if (cols > LCD_WIDTH) { small_bitmap.width = LCD_WIDTH; small_bitmap.height = (int)(((float)LCD_WIDTH / (float)cols) * (float)rows); } else { /* rows > LCD_HEIGHT */ small_bitmap.width = (int)(((float)LCD_HEIGHT / (float)rows) * (float)cols); small_bitmap.height = LCD_HEIGHT; } small_bitmap.data = (char*)lcd_buf; smooth_resize_bitmap( &orig_bitmap, &small_bitmap ); rb->lcd_bitmap((fb_data*)small_bitmap.data, 0, 0, small_bitmap.width, small_bitmap.height); } else { rb->lcd_bitmap((fb_data*)orig_bitmap.data, 0, 0, cols, rows); } rb->lcd_update(); rb->button_get(true); return PLUGIN_OK; }