📄 cnmutil.c
字号:
/*************************************************************************
CNMUtil.c
This is the CobraNet Module program utilities file. Utilities include
an accurate timing function, a hex switch read function, FPGA
loading routine and some MIB variable support routines.
Copyright (C) 2001-2004 by Cirrus Logic Inc. All Rights Reserved
*************************************************************************/
#include <8051.h>
#include <intrpt.h>
#include <conio.h>
#include "serial.h"
#include "hostport.h"
#include "command.h"
#include "test.h"
#include "led.h"
#include "mystrings.h"
#include "cnmutil.h"
extern unsigned char gWHICH_MODULE; //which is present? CM1 or CM2
extern void waiting( unsigned short delay1, unsigned char delay2 ) {
//this routine provides an accurate time delay.
//delay1 and delay2 are passed in registers and those are treated
//separately as chars. see 8051 programming manual for more detail.
//assembly was used to allow for a more controlled way of determining
//the exact time delay. See manual for parameter passing details.
//delay1 and delay2 are passed in registers R3,R4, and R5
//The delay is approx...
// ( 84 + 48 * ( 3 + R4 + 257 * R5 + R3 * ( 257 + 65536 ) ) ) / clock
//Note: any interrupts will affect the timing.
//Half for six cycle operation.
#asm
x1:
mov a,r4
dec r4
bnz x1
mov a,r5
dec r5
bnz x1
mov a,r3
dec r3
bnz x1
#endasm
}
extern unsigned short get_hex_switches( unsigned char update_hex ) {
//this routine shifts the contents of the shift registers (HC165)
//supporting the hex switches into the 8051
unsigned char i;
static unsigned short hex_value = 0;
unsigned short bit_value = 1;
if ( update_hex ) {
hex_value = 0;
mHEX_SHIFT = 0; //load the hex switch data (latch hex switch data)
mHEX_SHIFT = 1; //put back into shift mode
mHEX_DATA_OUT = 0; //leave zero for now
//clock the data into the 8051
for ( i = 0; i < 16; i++ ) {
if ( mHEX_DATA_IN ) //read bit
hex_value |= bit_value;
bit_value <<= 1;
mHEX_CLOCK = 0; //clock data
mHEX_CLOCK = 1;
}
}
return( hex_value );
}
extern void set_sysname( void ) {
//sets the SNMP "sysname" variable
unsigned char error_code;
unsigned char i,j;
code char * name_base_ptr = ( code char * ) str_SysName;
unsigned long name_loc_ptr = cSYSNAME_LOC_ptr; //long but a pointer
unsigned char dsp_word[ 4 ];
//poke length,last 4 are for the switch value
error_code = Host_Poke( name_loc_ptr++, cSYS_NAME_LEN + 4 ); //
for( i = 0; i < ( cSYS_NAME_LEN / gWHICH_MODULE ); i++ ) {
for( j = 0; j < 4; j++ )
if ( ( j == 0 ) && ( gWHICH_MODULE == cHOST_CM1 ) )
dsp_word[ 0 ] = '0'; //set first byte to "zero"
else
dsp_word[ j ] = *name_base_ptr++;
error_code = Host_Poke( name_loc_ptr++, *( ( long * )dsp_word ) );
}
//append switch value to system name
set_syshex( get_hex_switches( cUPDATE_HEX ) );
}
extern void set_syshex( unsigned short syshex_int ) {
//appends switch value in ASCII to MIB variable sysNAME
unsigned char error_code;
unsigned long name_loc_ptr = cSYSNAME_LOC_ptr + 1 +
( cSYS_NAME_LEN / ( gWHICH_MODULE + 2 ) );
char * dsp_word_ptr;
dsp_word_ptr = long2str( ( long ) syshex_int, cLEADING_ZEROS,
cFOUR_BYTES );
if ( gWHICH_MODULE == cHOST_CM1 ) {
//upper three hex bytes to the right three positions
error_code = Host_Poke( name_loc_ptr++,
*( ( long * ) ( dsp_word_ptr - 1 ) ) );
//point to last byte in second MSB position
error_code = Host_Poke( name_loc_ptr,
( *( ( long * ) ( dsp_word_ptr + 2 ) ) )
& 0xFF0000 );
}
else
error_code = Host_Poke( name_loc_ptr, *( ( long * ) dsp_word_ptr ) );
}
extern void check_hex( void ) {
unsigned short current_hex;
current_hex = get_hex_switches( cNO_UPDATE_HEX );
if ( current_hex != get_hex_switches( cUPDATE_HEX ) ) {
current_hex = get_hex_switches( cNO_UPDATE_HEX );
waiting( 0x0C,0x01 ); //wait just a bit for a debounce
//if still same then keep
if ( current_hex == get_hex_switches( cUPDATE_HEX ) ) ;
set_sysname();
//otherwise leave with no changes
}
}
extern void load_FPGA() {
unsigned short i;
code char * xdata_ptr = ( char * ) cFPGA_START_ptr; //pointer to FPGA data
far char * xlocation_ptr = ( far char * ) cFPGA_LOC_ptr; //ptr to FPGA
char * led_ptr = ( char * ) cLED_ptr;
static near unsigned char fpga_loaded = 0;
//the following code is needed to establish if the FPGA has already
//been programmed. When the code starts it moves a bunch of strings
//into external SRAM but external SRAM is not available until the
//FPGA has been loaded. If the FPGA has been loaded the LED registers
//are available to read and write. A system reset does not affect the
//FPGA because the 8051 controls the reset to the FPGA so once the FPGA
//is loaded it stays viable. The code below tests the LED registers and
//if they don't pass the write/read pattern then a variable is set to
//direct the 8051 code to reset itself after the FPGA has been loaded.
*led_ptr++ = 1;
*led_ptr++ = 0;
*led_ptr++ = 1;
led_ptr = ( char * ) cLED_ptr;
if ( *led_ptr++ == 1 )
if ( *led_ptr++ == 0 )
if ( *led_ptr++ == 1 ) {
led_ptr = ( char * ) cLED_ptr;
*led_ptr++ = 0;
*led_ptr++ = 1;
*led_ptr++ = 0;
led_ptr = ( char * ) cLED_ptr;
if ( *led_ptr++ == 0 )
if ( *led_ptr++ == 1 )
if ( *led_ptr++ == 0 )
fpga_loaded = 1;
}
mFPGA_PROG = 0;
waiting( 0,0 ); //kill a little time, about 11 useconds.
mFPGA_PROG = 1; //set init bit to start configuration
while ( mFPGA_INIT == 0 )
; //wait for init to go high
waiting( 0,0 ); //kill a little more time
*xlocation_ptr = 0; //need to do one bogus write at the start
for ( i = 0; i < cNUM_XBYTES; i++ ) {
*xlocation_ptr = *xdata_ptr++;
}
if ( !fpga_loaded ) { //reset the processor,
#asm
ljmp 0
#endasm
}
}
extern unsigned short swapBytes( unsigned short the_short ) {
return ( ( ( the_short >> 8 ) & 0xFF ) + ( the_short << 8 ) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -