?? sclk.c
字號:
* in the disk_position variable. * * When the carousel rotates from disk1 to disk5, the CAROUSEL_SENSOR * would have the following pattern. * _ _ _ _ _ _ _ _ _ _ _ _ _ _ *| |_| |___| |____| |_| |____| |_| |_____| |_| |___| |_| |_| |____| |_| |__ ... * stop disk_1 stop disk_2 stop Disk_3 stop * _ _ _ _ _ _ _ _ _ _ _ _ _ * ...___| |_| |_| |_| |____| |_| |_____| |_| |_| |_| |_| |____| |_| |_...... * disk_4 stop disk_5 stop * * Every disk position is represented by the number of spike between every * two STOP (or disk break) pattern and the time between that last spike * of a disk position and the beginning of the STOP pattern. This time * is the longest between disk1 and its STOP pattern, and shortest * between disk5 and its STOP pattern. TVM data sheet says this time * should be 300ms for disk1 and 200ms for disk5, and others disks have * timing in between 200ms and 300ms. The HIGH timing for every spike * of the disk number should be for about 15ms. The code counts the number * of 15ms spikes for determining the disk position. * * This routine is divided into two sections: Powerup and Normal Rotation. * * For powering, the disk rotating in disk1,2,3,4,5 direction. It will * stop on the first disk it finds after the powering up position. If * there are no disk, it will stop at the last empty position. If there * is only one disk in the powering up position, the carousel will rotate * all the way around and stop at the powering up position. * * The second section handles the disk rotation when rotating after the * powerup sequece. It can rotate in either direction for the number * of disk positions specified in the global variable "home_many_disk". * * The stop sequence is done by toggling one of the two carousel direction * control signals. * * To Start Rotation: * Setting changer_control_register to 0x8001 would cause the power up * carousel roation sequece. * Setting changer_control_register to 0x8000 would initiate the nomal * disk rotation operation. Setting changer_control_register to * 0x8000 | ROTATE_CCW will result in 0x8040 written to the register, * ant causing the carousel to rotate in disk5,4,3,2,1 direction. * The global variable, disk_position, that contains the current disk * position is automatically update in the ISR. It should be read * only outside of this routine. * * Notes: The TVM carousel can be rotated in disk1,2,3,4,5 direction or * in the disk5,4,3,2,1 direction. When rotated in disk1,2,3,4,5 direction, * the number of spike is the actual disk position plus 1. I.e. 1 spike is * disk2, 2 spikes is disk3...5 spickes is disk1. * * Bugs: I have found out that the variable disk_position can not be * update in the main code. So make sure that disk_position is read * only. Never found out why it's this way; it's probably the compiler. */int powerup_state; /* state name for powerup rotation Finite State Machine */int rotate_state; /* state name for post powerup rotation FSM */int half_rotate_state; /* state name for half rotation of OPEN when disk is playing */int spike_counter; /* counting the number of disk position spikes */int first_disk_present; /* FLAG, 1: power up carousel position has disk; 0: no disk */int disk_counter; /* counts how many disk positions we have gone through powerup rotating FSM */ void rotate_carousel_and_find_position(void){ PI = get_PI(); if (PI & 0x02) { /* can we rotate or not?*/ changer_control_register = 0; return; } if (changer_control_register & 0x0001) /* do power up */ { switch (powerup_state) { case 0: /* start rotation */ /* init first_disk_present, spike_counter, and disk_counter */ first_disk_present = (DISK_PRESENT) ? 0 : 1; if (!(first_disk_present)) { /* double check, abate chances of glitches on EAUX9 */ first_disk_present = (DISK_PRESENT) ? 0 : 1; } spike_counter = 0; disk_counter = 0; /* enable rotation */ CLEAR_CAROUSEL_CW; SET_CAROUSEL_CCW; powerup_state = 10; /* 1 */ six_msec_counter = 0; break; case 10: if (!(CAROUSEL_SENSOR_HIGH)) { powerup_state = 1; six_msec_counter = 0; } break; case 1: /* look for the 200msec+ low */ if (CAROUSEL_SENSOR_HIGH) { if (six_msec_counter > 25 ) { /* found the 200msec+ low */ powerup_state = 2; six_msec_counter = 0; } else { powerup_state = 10; six_msec_counter = 0; } } break; case 2: /* is this a 15msec spike?? */ if (!(CAROUSEL_SENSOR_HIGH)) { if (six_msec_counter < 4) { /* this is a 15msec spike*/ powerup_state = 3; spike_counter++; six_msec_counter = 0; } else { /* oops, this is not a 15msec spike. start all over */ six_msec_counter = 0; powerup_state = 10; /* 1; */ } } break; case 3: /* is this a 35msec LOW?? or a post position spike 200 msec+ LOW???*/ if (CAROUSEL_SENSOR_HIGH) { if ((six_msec_counter > 1)&&(six_msec_counter < 8)) { /* found the 35msec low */ powerup_state = 2; six_msec_counter = 0; } else if (six_msec_counter > 7) { /* post spike 200msec+ Low */ powerup_state = 4; disk_position = spike_counter + 1; /* carousel bug, disk_position is spike count+1 */ if (disk_position == 6) { disk_position = 1; } spike_counter = 0; /* clear spike_counter for next disk position */ disk_counter++; six_msec_counter = 0; } else if (six_msec_counter < 2) { /* glitch !!! start all over */ six_msec_counter = 0; powerup_state = 1; } } break; /* Wait for 18msec and detect if disk is present. Start carousel STOP sequence if * 1) disk presents, or 2) looked through all positions and found no disk. */ case 4: if (six_msec_counter > 4) { have_disk = (DISK_PRESENT) ? 0 : 1; if (!(have_disk)) { /* double check for disk presence, in case of glitches */ have_disk = (DISK_PRESENT) ? 0 : 1; } if (((changer_control_register &0x0002)&& (!have_disk))|| (!(changer_control_register &0x0002))&& ( have_disk || ((disk_counter==4)&&(first_disk_present==0)) || ((disk_counter==5)&&(first_disk_present == 1)))){ /* start carousel STOP sequence */ SET_CAROUSEL_CW; powerup_state = 5; /* continue sending out STOP waveform */ } else { /* no disk in current position, look at the next position*/ six_msec_counter = 0; powerup_state = 1; } } break; case 5: /* sending out STOP waveform, LOW */ if (CAROUSEL_SENSOR_HIGH) { /* CLEAR_CAROUSEL_CW;*/ powerup_state = 6; } else { powerup_state = 9; } break; case 6: /* continueing STOP waveform, HIGH */ if (CAROUSEL_SENSOR_HIGH) { SET_CAROUSEL_CW; six_msec_counter = 0; powerup_state = 7; } else { powerup_state = 9; } break; case 7: /* continureing STOP waveform, LOW after 18msec */ if (CAROUSEL_SENSOR_HIGH){ if (six_msec_counter > 2) { CLEAR_CAROUSEL_CW; powerup_state = 8; } else { powerup_state = 9; } } break; case 8: /* continueing STOP waveform, HIGH */ if (CAROUSEL_SENSOR_HIGH) { SET_CAROUSEL_CW; powerup_state = 5; /* continueing STOP waveform in state 5 */ } else { powerup_state = 9; } break; case 9: SET_CAROUSEL_CW; changer_control_register &= 0x7FFF; powerup_state = 0; /* reset the FSM */ break; default: break; } /* end switch(powerup_state) */ } else if ((changer_control_register & 0xFF00)==0x8800) { /* do half rotation for OPEN while disk is playing */ switch (half_rotate_state) { case 0: if(changer_control_register & 0x0040) CLEAR_CAROUSEL_CCW; else CLEAR_CAROUSEL_CW; six_msec_counter = 0; half_rotate_state = 1; break; case 1: if (six_msec_counter > 59) { SET_CAROUSEL_CW; SET_CAROUSEL_CCW; half_rotate_state = 2; } break; case 2: if(changer_control_register & 0x0040) CLEAR_CAROUSEL_CCW; else CLEAR_CAROUSEL_CW; half_rotate_state = 3; break; case 3: SET_CAROUSEL_CW; SET_CAROUSEL_CCW; six_msec_counter = 0; half_rotate_state = 4; break; case 4: if (six_msec_counter > 2) { if(changer_control_register & 0x0040) CLEAR_CAROUSEL_CCW; else CLEAR_CAROUSEL_CW; half_rotate_state = 5; } break; case 5: SET_CAROUSEL_CW; SET_CAROUSEL_CCW; half_rotate_state = 0; if (loader_state == 5) { loader_state = 7; } changer_control_register = 0x0000; break; default: break; } /* finished half rotation */ } else { /* rotate to a position, direction and how much to turn must be given */ switch (rotate_state) { case 0: if (how_many_disk == 0) how_many_disk = 1; disk_counter = 0; if (changer_control_register & CAROUSEL_CCW) CLEAR_CAROUSEL_CCW; else CLEAR_CAROUSEL_CW; rotate_state = 1; break; case 1: /* in search for a LOW, any LOW */ if (!(CAROUSEL_SENSOR_HIGH)) { rotate_state = 2; six_msec_counter = 0; } break; case 2: /* is this a 200msec+ LOW???? */ if (CAROUSEL_SENSOR_HIGH) { if (six_msec_counter > 28) { /* found the 200msec+ LOW, look for 30msec+ HIGH next*/ rotate_state = 3; six_msec_counter = 0; } else { /* start over, looking for a 200msec+ LOW */ rotate_state = 1; } } break; case 3: /* looking for the 18msec+ HIGH */ if (CAROUSEL_SENSOR_HIGH) { if (six_msec_counter > 4) { disk_counter++; /* updating disk_position */ if (changer_control_register & 0x0300) ; else{ if (changer_control_register & CAROUSEL_CCW) { disk_position--; if (disk_position == 0) { disk_position = 5; } } else { disk_position++; if (disk_position == 6) { disk_position = 1; } } } if (disk_counter == how_many_disk) { if(changer_control_register & 0x0200) { changer_control_register &= 0x00ff; changer_control_register |= 0x8800; rotate_state = 0; /* continue on the half rotate */ } else { /* finished rotating the number of disks that's asked */ /* sending out stop sequence */ have_disk = (DISK_PRESENT) ? 0 : 1; if (have_disk == 0) { /* double check if disk is present */ have_disk = (DISK_PRESENT) ? 0 : 1; } SET_CAROUSEL_CCW; SET_CAROUSEL_CW; rotate_state = 4; } } else { /* more disk rotations required */ rotate_state = 1; } } } else { /* OOPS! GLITCH? */ rotate_state = 1; } break; case 4: /* STOP sequence continues, clearing */ if (CAROUSEL_SENSOR_HIGH) { if (changer_control_register & CAROUSEL_CCW) /*CLEAR_CAROUSEL_CCW; */ SET_CAROUSEL_CCW; else /* CLEAR_CAROUSEL_CW; */ SET_CAROUSEL_CCW; rotate_state = 5; } else { rotate_state = 8; } break; case 5: /* setting to HIGH */ if (CAROUSEL_SENSOR_HIGH ) { if (changer_control_register & CAROUSEL_CCW) SET_CAROUSEL_CCW; else SET_CAROUSEL_CW; rotate_state = 6; six_msec_counter = 0; } else { rotate_state = 8; } break; case 6: /* setting to LOW after 18 ms */ if (CAROUSEL_SENSOR_HIGH) { if (six_msec_counter > 3) { if (changer_control_register & CAROUSEL_CCW) CLEAR_CAROUSEL_CCW; else CLEAR_CAROUSEL_CW; rotate_state = 7; } } else { rotate_state = 8; } break; case 7: /* setting to HIGH */ if (CAROUSEL_SENSOR_HIGH) { if (changer_control_register & CAROUSEL_CCW) SET_CAROUSEL_CCW; else SET_CAROUSEL_CW; rotate_state = 4; six_msec_counter = 0; } else { rotate_state = 8; } break; case 8: SET_CAROUSEL_CCW; SET_CAROUSEL_CW; rotate_state = 0; if(changer_control_register & 0x0100) /* finished half rotate*/ { motor_control_register = 0xD000; /* now close the drawer */ changer_control_register = 0; } else changer_control_register &= 0x7FFF; break; } /* end of switch(rotate_state) */ } /* end of if statment */} /* end rotate_carousel_and_find_position() *//* void rotate_drawer_motor() * Controls the In/Out the drawer and the Up/Down of the pickup. * This process is controlled through the motor_control_register. * [1xxx xxxx xxxx xxxx] start motor, it is set by main program * [x?xx xxxx xxxx xxxx] 1: counter clock wise 0: clock wise * [xx?? xxxx xxxx xxxx] 00: rotate by one state, * 01: rotate by two states, * 10: rotate by three states, * 11: rotate by four states. * [xxxx 1xxx xxxx xxxx] motor rotation has started. * [0xxx xxxx xxxx xxxx] motor stopped, this status is set to 0 by ISR. * */void rotate_drawer_motor(){ static int old_PI, state_counter, target_state; if (!(motor_control_register & 0x8000)) { return; } if (!(motor_control_register & 0x0800)) { motor_timer = 0; state_counter = 0; old_PI = PI; if (motor_control_register & 0x4000) { rotate_motor_CCW; } else { rotate_motor_CW; } target_state = ((motor_control_register >> 12) & 3) + 1; /* target_state has the number of states that we want to move by */ motor_control_register |= 0x0800; } else if ((motor_control_register & 0x8800)==0x8800) { PI = get_PI(); while (PI != get_PI()) { /* double check on PI value */ PI = get_PI(); } while (PI != get_PI()) { /* tripple check on PI value */ PI = get_PI(); } while (PI != get_PI()) { /* quadruple check on PI value */ PI = get_PI(); } while (PI != get_PI()) { /* "sinco" (5th time) check on PI value */ PI = get_PI(); } if (old_PI != PI) { state_counter++; if (target_state == state_counter) { stop_motor; motor_control_register &= 0x7FFF; if ((loader_state==5)&&(target_state==2) && (!(motor_control_register & 0x4000))) { /* finished try OPEN while disk playing, start 1/2 rotate */ changer_control_register = 0x8800; half_rotate_state = 0; } else if ((loader_state==7) && (target_state==2) && (motor_control_register &0x4000)) { loader_state = 5; } /*---------------------------*/ else if ((loader_state==3) && (target_state==2) && ((motor_control_register & 0x4000))) { /* finished tray OPEN while pickup is down, start 2 position rotate */ how_many_disk = 2; changer_control_register = 0x8000; /* 2 position rotate , in state: OPEN, pickup down */ loader_state = 1; } else if ((loader_state==1) && (target_state==2) && (!(motor_control_register &0x4000))) { /* finished tray CLOSE while pickup is down, start 3 position rotate */ how_many_disk = 3; changer_control_register = 0x8000; /* 3 position rotate , in state: CLOSE, pickup down */ loader_state = 3; } /*--------------------------*/ } else { old_PI = PI; motor_timer = 0; } } else { if (motor_timer > 400) { /* 2.4 second timeout, not finalized */ motor_fault_error = 1; stop_motor; motor_control_register &= 0x7FFF; } } } return;}int get_PI(void){ int new_PI=0; /* return value */ if (PI_1_HIGH) /* PI_1 */ new_PI = 0x0001; if (PI_2_HIGH) /* PI_2 */ new_PI = new_PI | 0x0002; return new_PI;}#endif /* CUST8_5DISK */#endif /* TVM_MODULE */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -