📄 cam_control_fw.c
字号:
/*----------------------------------------------------------------------------*\| || Copyright (C) 2003, James A. Cureington || tonycu * users_sourceforge_net || || This program is free software; you can redistribute it and/or || modify it under the terms of the GNU General Public License || as published by the Free Software Foundation; either version 2 || of the License, or any later version. || || This program is distributed in the hope that it will be useful, || but WITHOUT ANY WARRANTY; without even the implied warranty of || MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the || GNU General Public License for more details. || || You should have received a copy of the GNU General Public License || along with this program; if not, write to the Free Software || Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. || || || Tony Cureington || November 30, 2002 || || || This file is associated with the ezusb2131 Linux downloader project. The || project can be found at http://ezusb2131.sourceforge.net. || || this file derived from pp.c || || pp.c Copyright (C) 2002, Michael Hetherington || chinook * pacific_net_sg || || pp.c based on sunkbd_hid.c || sunkbd_hid.c Copyright (C) 2001, Arnim Laeuger || arnim * users_sourceforge_net || || :set tabstop=3 || :set softtabstop=3 || :set shiftwidth=3 || :set smarttab || :mkv ~/.vimrc || || X:set expandtab || |\*----------------------------------------------------------------------------*//******************************************************************************* * * $Id: cam_control_fw.c,v 1.1 2003/02/21 06:50:35 tonycu Exp $ * ******************************************************************************/#include <stdio.h>#include <string.h>#include <8051.h>#include "cam_common.h"#include "cam_control_fw.h"#define HEART_BEAT_A7 0 /* only one of the "BEAT" define should be true */#define HEART_BEAT_C3 0 /* at one time */#define DATA_BEAT_A7 0#define DATA_BEAT_C3 1#define DELAY_PER_PERIOD 0 /* number of extra servo periods per degree * of movement - makes the servo move slower */extern void wait_msec(unsigned short);static xdata setup_data * data sdata = (xdata setup_data *)&SETUPDAT;static xdata cc_command * data cam_command = (xdata cc_command *)&OUT1BUF;static xdata cc_info * data cam_info = (xdata cc_info *)&IN1BUF;idata static unsigned short center_usecs;idata static unsigned short pulse_frequency;idata static pwm pwm_message;idata static volatile char timer1_action;idata unsigned volatile short usecs;idata unsigned volatile short timer1_usecs_remaining;idata static byte th1_remaining;idata static byte tl1_remaining;/* below vars are assigned only in timer0_isr, the are global only *//* for other functions to read - not write! */idata static short current_horizontal_pos;idata static short current_vertical_pos;idata static short final_horizontal_pos;idata static short final_vertical_pos;idata static char ep1in_pending;#if DELAY_PER_PERIODidata char servo_delay_count;#endif /* DELAY_PER_PERIOD *//* blink port A7 the number of specified times *//* with a one second pause between the number of *//* specified blinks - used for debugging */#if 1 /* EZUSB_DEBUG */static voidblink_portA7(unsigned char blinks, unsigned char forever){ unsigned int i; PORTACFG &= ~0x80; OEA |= 0x80; do { for (i=0; i < (blinks*2); i++) { if (i%2) { OUTA &= ~0x80; /* off */ } else { OUTA |= 0x80; /* on */ } wait_msec(1000); } OUTA &= ~0x80; /* off */ wait_msec(2000); } while (forever); return; /* not reached */}#endif /* EZUSB_DEBUG *//**************************************************** * get_descriptor() * see TRM v1.9 page 7-12 (133) for info on Get_Descriptor * requests ****************************************************/static void get_descriptor(void) using 1{ switch (sdata->wValueH) { case GET_DEVICE_DESCRIPTOR: CLEAR_HSNAK(); /* clr hsnak first, per TRM v1.9 page 7-14 (135) */ SUDPTRH = HI_BYTE(dev_desc); SUDPTRL = LOW_BYTE(dev_desc); break; case GET_CONFIG_DESCRIPTOR: CLEAR_HSNAK(); SUDPTRH = HI_BYTE(conf_desc); SUDPTRL = LOW_BYTE(conf_desc); break; case GET_STRING_DESCRIPTOR: if (sdata->wValueL < NUM_STRINGS) { CLEAR_HSNAK(); SUDPTRH = HI_BYTE(string_index[sdata->wValueL]); SUDPTRL = LOW_BYTE(string_index[sdata->wValueL]); } else { EP0_STALL(); } break; default: EP0_STALL(); break; }}/**************************************************** * get_status() ****************************************************/static void get_status(void) using 1{ switch (sdata->bmRequestType) { /* device status */ case 0x80: /* bus powered/no wakeup */ in0buf[0] = 0; in0buf[1] = 0; IN0BC = 0x02; CLEAR_HSNAK(); break; /* interface status */ case 0x81: if(sdata->wIndexL == 0){ in0buf[0] = 0; in0buf[1] = 0; IN0BC = 0x02; CLEAR_HSNAK(); } else { EP0_STALL(); } break; /* endpoint status */ case 0x82: switch (sdata->wIndexL) { /* endpoint 0 IN/OUT */ case 0x00: case 0x80: in0buf[0] = 0; in0buf[1] = 0; IN0BC = 0x02; CLEAR_HSNAK(); break; /* endpoint 1 IN/OUT */ case 0x01: case 0x81: in0buf[0] = 0; in0buf[1] = 0; IN0BC = 0x02; CLEAR_HSNAK(); break; default: EP0_STALL(); break; } break; default: EP0_STALL(); break; }}/**************************************************** * set_interface() ****************************************************/static void set_interface(void) using 1{ /* below is left here as a place holder... */#ifdef DONT_DO /* only one interface supported */ if (sdata->bmRequestType == 0x01 && sdata->wIndexL == 0x00) { switch (sdata->wValueL) { case 0x00: TOGCTL = 0x01; /* select endpoint 1 OUT */ TOGCTL = 0x21; /* toggle */ OUT1BC = 0x00; /* write any value */ TOGCTL = 0x12; /* select endpoint 2 IN */ TOGCTL = 0x32; /* toggle */ IN2CS |= 0x02; /* clear busy bit */ TOGCTL = 0x14; /* select endpoint 4 IN */ TOGCTL = 0x34; /* toggle */ IN4CS |= 0x02; /* clear busy bit */ CLEAR_HSNAK(); break; default: EP0_STALL(); break; } } else { EP0_STALL(); }#else /* DONT_DO */ EP0_STALL();#endif /* DONT_DO */}/**************************************************** * send cc_info struct in ep0in buffer ****************************************************/voidsend_cc_info(void){ if (IN1CS & 0x02) { /* buffer is busy (being used by SIE?) */ ep1in_pending = 1; return; } cam_info->current_hdeg = (current_horizontal_pos / (NUM_STOPS/NUM_DEGREES)); cam_info->current_vdeg = (current_vertical_pos / (NUM_STOPS/NUM_DEGREES)); cam_info->final_hdeg = (pwm_message.horizontal_pos / (NUM_STOPS/NUM_DEGREES)); cam_info->final_vdeg = (pwm_message.vertical_pos / (NUM_STOPS/NUM_DEGREES)); IN1BC = sizeof(cc_info);}/**************************************************** * endpoint0_out() * process command from host * the pwm_message is handled in timer0_isr ****************************************************/voidendpoint1_out(void){ if (cam_command->command & CC_COMMAND_MOVE) { /* an out of range degrees means not to change the position; * we must check for the max & min degrees and move in that * direction if we have not reached the true max or min. * i.e. the current vertical degrees is limited to +-45 degrees due * to the hardware setup, so a value <=90 but greater than our current * max should cause movement up to the max possible vertical degrees, * in our case 45 degrees. */ /* horizontal position change */ if ((cam_command->new_horizontal_deg >= MIN_HORIZONTAL) && (cam_command->new_horizontal_deg <= MAX_HORIZONTAL)) { pwm_message.horizontal_pos = cam_command->new_horizontal_deg * (NUM_STOPS/NUM_DEGREES); } else if ((cam_command->new_horizontal_deg <= MAX_DEGREES) && (cam_command->new_horizontal_deg > MAX_HORIZONTAL)) { pwm_message.horizontal_pos = MAX_HORIZONTAL * (NUM_STOPS/NUM_DEGREES); } else if ((cam_command->new_horizontal_deg >= MIN_DEGREES) && (cam_command->new_horizontal_deg < MIN_HORIZONTAL)) { pwm_message.horizontal_pos = MIN_HORIZONTAL * (NUM_STOPS/NUM_DEGREES); } /* vertical position change */ if ((cam_command->new_vertical_deg >= MIN_VERTICAL) && (cam_command->new_vertical_deg <= MAX_VERTICAL)) { pwm_message.vertical_pos = cam_command->new_vertical_deg * (NUM_STOPS/NUM_DEGREES); } else if ((cam_command->new_vertical_deg <= MAX_DEGREES) && (cam_command->new_vertical_deg > MAX_VERTICAL)) { pwm_message.vertical_pos = MAX_VERTICAL * (NUM_STOPS/NUM_DEGREES); } else if ((cam_command->new_vertical_deg >= MIN_DEGREES) && (cam_command->new_vertical_deg < MIN_VERTICAL)) { pwm_message.vertical_pos = MIN_VERTICAL * (NUM_STOPS/NUM_DEGREES); } pwm_message.new_command = 1; } if (cam_command->command & CC_COMMAND_STOP) { pwm_message.horizontal_pos = current_horizontal_pos; pwm_message.vertical_pos = current_vertical_pos; pwm_message.new_command = 1; } if (cam_command->command & CC_COMMAND_INFO) { send_cc_info(); }}/**************************************************** * usb_isr() * ****************************************************/static void usb_isr(void) interrupt 8 using 1 { CLEAR_INT2(); /* clear INT2 interrupt */#if DATA_BEAT_A7 OUTA |= 0x80; /* turn port A7 on, it is turned off in the isr */#endif /* DATA_BEAT_A7 */#if DATA_BEAT_C3 OUTC &= ~0x08; /* turn port C3 on (low), it is turned off in the isr */#endif /* DATA_BEAT_C3 */ if (USBIRQ & 0x01) { /* this is an SUDAV interrupt */ USBIRQ = 0x01; /* clear SUDAV interrupt */ /* standard requests */ if ((sdata->bmRequestType & REQUEST_TYPE_MASK) == STANDARD_REQUEST_TYPE) { switch (sdata->bRequest) { case GET_STATUS_REQUEST: get_status(); break; case GET_DESCRIPTOR_REQUEST: get_descriptor(); break; case GET_CONFIG_REQUEST: /* only one configuration is supported */ if (sdata->bmRequestType == 0x80 && sdata->wLengthL == 0x01) { in0buf[0] = 0x01; IN0BC = 0x01;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -