⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alt_touchscreen.c

📁 基于NIOSII软核的触摸屏驱动软体.采用的是AD7843触摸屏数字转换器
💻 C
📖 第 1 页 / 共 3 页
字号:
//////////////////////////////////////////////////////////////////staticunsigned int get_coherent_pen_data     (alt_touchscreen_pen_state*       pen_state,     alt_touchscreen_pen_adc_data*    pen_adc_data,     alt_touchscreen_axis_swap_choice swap_xy,     int* pen_down,     int* x_adc_sample,     int* y_adc_sample){  int x;  int y;  int sample_number;    // Look at the data over and over again until we DIDN'T get an  // interrupt while we were in the middle of it.  do {    sample_number = pen_state->sample_number;    *pen_down     = pen_state->pen_down;    x     	  = pen_adc_data->x;    y     	  = pen_adc_data->y;  } while (sample_number != pen_state->sample_number);  // If some goober wired-up the ADC wrong (as on the EEK), then you  // can un-do this in software.  Yay, software--savior of goobers  // everywhere.   if (swap_xy == ALT_TOUCHSCREEN_SWAP_XY) {    *x_adc_sample = y;    *y_adc_sample = x;  } else {    *x_adc_sample = x;    *y_adc_sample = y;  }  return sample_number;}////////////////////////////////////////////////////////////////// Timer (alarm) callback////   If you arrange for this thing to get called at ~60Hz, then the //   screen will be sampled at (roughly) a quarter of that rate,//   because  it takes two samples to get each of X and Y.////   This function just dispatches commands to the SPI port, //   and acknowledges that it did so by setting the//   "transmit_request" variable to "0."//   It doesn't do anything else.  It doesn't even know what the//   commands mean. It just sends the commands it's asked to send; //   acknowledges that they were sent (basically: so it doesn't send//   them twice), and exits.//////////////////////////////////////////////////////////////////staticalt_u32 alarm_callback (void* context){  alt_touchscreen_alarm_context* alarm_context =     (alt_touchscreen_alarm_context*) context;  alt_touchscreen_hardware*         hardware  = alarm_context->hw;  alt_touchscreen_sample_machine*   machine   = alarm_context->sample_machine;   alt_touchscreen_pen_state*        pen_state = alarm_context->pen_state;  alt_touchscreen_event_flag_group* flags     = alarm_context->event_flags;  int pen_detect;    // If the sample-machine isn't ready, it could only be because it's  // still busy.  If it's busy, we don't want   // to go around starting any action of any kind.  //   if (!sample_machine_ready(machine)) {    // Note that this should never happen.    // This means that we're "falling behind," and the sample-machine    // isn't done with the last sample when the alarm goes off asking    // for the next sample.    //    // Make a note of this in a debug flag,     //screen->sampling_running_behind_alarm++;    return alarm_context->nticks;  }  // We have to read the pen-state inbetween samples...because that's  // the way the AD7843 works.  "Inbetween samples" is right now,  // before we kick-off another sample sequence.  // Update our flags & states & such with this new pen-down data:  //  pen_detect = hardware_pen_detect (hardware);  if (pen_detect) {    // Launch a sample-sequence only if the pen is down.    hardware_send_spi_command  (hardware,         sample_machine_next_command      (machine),        sample_machine_link_next_command (machine));  } else {    // If the pen is up, this is actually important information.    // there's no reason to launch another sample...but if we don't    // update the pen-state, our clients won't know that the pen has    // been lifted.  And, obviously:  They need to know.      pen_state_update_from_detect_sample (pen_state, pen_detect);      event_flag_group_update_from_pen_state (flags, pen_state);  }  return alarm_context->nticks;}////////////////////////////////////////////////////////////////////  alt_touchscreen_get_pen////  Public API////  Provides the caller with a full, coherent sample of the current//  pen-state.  Returns the "serial number" of the x,y,pen sample//  acquired (so apps can see when the data changes).////  If pen_down == 0, then x & y are meaningless.////  This DOES NOT cause any actual sampling of the hardware--that//  happens in the background.  This executes very quickly because//  (really) it just updates a couple of variables and does a little//  scaling arithmetic.//////////////////////////////////////////////////////////////////unsigned int alt_touchscreen_get_pen (alt_touchscreen* screen,				      int* pen_down,				      int* x,				      int* y){  unsigned int x_adc_sample  = 0;  unsigned int y_adc_sample  = 0;  unsigned int sample_number = 0;  sample_number = get_coherent_pen_data     (&(screen->pen_state),     &(screen->pen_adc_data),     screen->swap_xy,     pen_down,     &x_adc_sample,     &y_adc_sample );  // Note that we have to scale even if the pen isn't down.  // The value you get is the LAST LOCATION the pen was seen.  surface_scaler_compute_output (&(screen->surface_scaler),				 x_adc_sample,  y_adc_sample,				 x,             y             );  return sample_number;}//////////////////////////////////////////////////////////////////  //  alt_touchscreen_stop()////   Public API.////   disables ISRs, unregisters alarms, and un-registers callbacks.//   and returns touchscreen state-variables to some//   harmless condition.//   ////////////////////////////////////////////////////////////////void alt_touchscreen_stop(alt_touchscreen* screen){  // Turn off alarms  alt_alarm_stop (&(screen->alarm));  // Disable IRQs in the SPI core itself.  hardware_stop (&(screen->hardware));  callback_registry_init (&(screen->callback_registry));}  ////////////////////////////////////////////////////////////////////  alt_touchscreen_register_callback_func////  Public API//// You pass-in a pointer to your callback-function, and indicate// whether you want to register it for pen-up or pen-down events.//// Pass NULL to un-register a callback.//// returns 0 on success.//// You can only register one callback for each event type.  You must// un-register it before you regster another one.  If you try to// register multiple callbacks for the same event-type, this function// will return a nonzero error code (and the preexisting callback will// still be registered).//// alt_touchscreen_stop() unregisters all callbacks.//////  Implementation://    This is just a wrapper around the registry-management function //    The wrapper hides the "registry" details from the caller, whilst//    preserving the modular testability of the "pure" registry functionality.////////////////////////////////////////////////////////////////////int alt_touchscreen_register_callback_func (    alt_touchscreen*                         screen,    alt_touchscreen_callback_trigger         callback_reason,    alt_touchscreen_event_callback_func      callback_func,    void*                                    context	   ){  return callback_registry_register_callback     (&(screen->callback_registry),      callback_reason,      callback_func,      context);}							      //////////////////////////////////////////////////////////////////// alt_touchscreen_event_loop_update////  Public API////  You call this function from your pen-management thread or, if you//  don't have an OS, whenever you can from your main while(1) loop. ////  This function DOES NOT drive the sensor or interact with the//  sensor at all.////  This is just a convenience-function for dispatching your//  registered callbacks.  ////  This may seem inconvenient....but it's not *very* inconvenient;//  and this way your callbacks run in application-context instead of//  ISR.////  This function returns nothing.////  Implementation://    This is just a wrapper around the registry-management function //    The wrapper hides the "registry" details from the caller, whilst//    preserving the modular testability of the "pure" registry functionality.// //////////////////////////////////////////////////////////////////void alt_touchscreen_event_loop_update (alt_touchscreen* screen){  alt_touchscreen_scaled_pen_data pen_data;  alt_touchscreen_get_pen(    screen, (&pen_data.pen_down), (&pen_data.x), (&pen_data.y));      callback_registry_dispatch_from_event_flag_group     (&(screen->callback_registry),      &(screen->event_flags      ),     &(pen_data)                );}////////////////////////////////////////////////////////////////////  alt_touchscreen_init////   Public API.  Starts the touchscreen sampling machinery////   returns zero if successful.////////////////////////////////////////////////////////////////int alt_touchscreen_init (alt_touchscreen* screen,			  alt_u32 spi_controller_base,			  alt_u32 spi_controller_irq_number,			  alt_u32 pen_detect_pio_base,			  int samples_per_second,			  alt_touchscreen_axis_swap_choice swap_xy){  int error = 0;  sample_machine_init    (&(screen->sample_machine));  pen_state_init         (&(screen->pen_state  ));  event_flag_group_init  (&(screen->event_flags));  pen_adc_data_init      (&(screen->pen_adc_data));  callback_registry_init (&(screen->callback_registry));  // It feels a little silly to do all of this "initialization of  // structures which just point to other structures,"  But this is  // The Way to inforce purity & separatin, giving functions only and  // exactly the minimal information they need to do their jobs.  // Decoupling in the name of testability and all that, eh what?   //  spi_isr_context_init   (&(screen->spi_isr_context),			  &(screen->hardware),			  &(screen->sample_machine),			  &(screen->pen_adc_data),			  &(screen->pen_state  ),			  &(screen->event_flags));  alarm_context_init     (&(screen->alarm_context),			  samples_per_second,			  &(screen->hardware),			  &(screen->sample_machine),			  &(screen->pen_state  ),			  &(screen->event_flags));    // Set some "harmless" scaling numbers.  These will just give   // the identity-transform on the A-to-D data.  Users have to call  // explicit scale-setting functions if they want to.  //  screen->swap_xy = swap_xy;    alt_touchscreen_calibrate_lower_left  (screen,					     0,      0,					     0,      0 );  alt_touchscreen_calibrate_upper_right  (screen,					  4095,   4095,					  4095,   4095 );    // Now clear-out the SPI controller and put it in a known state:  // This has the side-effect of registering the SPI interrupt  // handler.  error = hardware_init      (&(screen->hardware),			      spi_controller_base,			      spi_controller_irq_number,			      pen_detect_pio_base,			      &(screen->spi_isr_context));  if (error) {    alt_touchscreen_stop(screen);    return error;  }  // Set an alarm for regular sampling.      error = alt_alarm_start (&(screen->alarm),			   screen->alarm_context.nticks,			   alarm_callback,			   (void*) (&(screen->alarm_context)));  if (error) {    // Couldn't set alarm.    // Shut-down the entire touchscreen and return a failure code.    alt_touchscreen_stop(screen);    return error;  }   return 0;    // All happy; no error.}//////////////////////////////////////////////////////////////////// alt_touchscreen_calibrate_upper_right ////     --and--//// alt_touchscreen_calibrate_lower_left////  Public API//// The easiest way to do this is write your application and use the// default settings and print-out the X/Y coordinates continuously.////   First: Make sure you un-swap X and Y if they're swapped.  You do//   this when you initialize the touchscreen.////   Next: Put your pen in the upper-right and lower-left corners.//   write-down the X- and Y-values.  You'll use these as the//   "adc_value" numbers to pass into these routines.////   The "screen coordinates" are whatever your application wants to//   assign to those two corners of the screen.  ////   "Up/down" and "left/right" are whatever you consider them to be//   when you're holding the pen in one of these corners.  Just plug//   the numbers in an you'll get what you want.//   ////////////////////////////////////////////////////////////////void alt_touchscreen_calibrate_upper_right ( alt_touchscreen* screen, unsigned int x_adc_value, unsigned int y_adc_value, int x_screen_coordinate, int y_screen_coordinate ) {   surface_scaler_set_upper_right (&(screen->surface_scaler),				  x_adc_value,         y_adc_value,				  x_screen_coordinate, y_screen_coordinate);}void alt_touchscreen_calibrate_lower_left( alt_touchscreen* screen, unsigned int x_adc_value, unsigned int y_adc_value, int x_screen_coordinate, int y_screen_coordinate ) {   surface_scaler_set_lower_left (&(screen->surface_scaler),				 x_adc_value,         y_adc_value,				 x_screen_coordinate, y_screen_coordinate);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -