'{$STAMP BS2p} 'CONNECTIONS FROM THE BASIC STAMP TO THE EMBEDDED ETHERNET BOARD ' p0-p3 Crystal address bus a0-a3 ' p4 /RD ' p5 /WR ' p6 AEN ' p7 N/C ' p8-p15 Crystal data bus d0-d7 ' A0-A2 DAC serial connection bus ' A14-A16 ADC serial connection bus ' A7 Power amplifier pin ' ' See http://www.vermontlife.com/gary/crystal.html for information on the Embedded Ethernet Board ' See http://www.crystal/pubs/ftp/pubs/8900.pdf for information on the CS8900A ' ' Crystal CS8900 PacketPage equates ' portRxTxData CON $00 'Receive/Transmit data (port 0) portTxCmd CON $04 'Transmit Commnad portTxLength CON $06 'Transmit Length portPtr CON $0a 'PacketPage pointer portData CON $0c 'PacketPage data (port 0) ' ' CS8900 PacketPage Offsets ' ppProdID CON $0002 'Product ID Number ppIOBase CON $0020 'I/O Base Address ppIntNum CON $0022 'Interrupt number (0,1,2, or 3) ppMemBase CON $002C 'Memory Base address register (20 bit) ppRxCfg CON $0102 'Receiver Configuration ppRxCtl CON $0104 'Receiver Control ppTxCfg CON $0106 'Transmit Configuration ppBufCfg CON $010A 'Buffer Configuration ppLineCtl CON $0112 'Line Control ppSelfCtl CON $0114 'Self Control ppBusCtl CON $0116 'Bus Control ppISQ CON $0120 'Interrupt status queue ppRxEvt CON $0124 'Receiver Event ppTxEvt CON $0128 'Transmitter Event ppBufEvt CON $012C 'Buffer Event ppRxMiss CON $0130 'Receiver Miss Counter ppTxCol CON $0132 'Transmit Collision Counter ppLineSt CON $0134 'Line Status ppSelfSt CON $0136 'Self Status ppBusSt CON $0138 'Bus Status ppTxCmd CON $0144 'Transmit Command Request ppTxLength CON $0146 'Transmit Length ppIndAddr CON $0158 'Individual Address (IA) ppRxStat CON $0400 'Receive Status ppRxLength CON $0402 'Receive Length ppRxFrame CON $0404 'Receive Frame Location ppTxFrame CON $0A00 'Transmit Frame Location ' ' Register Numbers ' REG_NUM_MASK CON $003F REG_NUM_RX_EVENT CON $0004 REG_NUM_TX_EVENT CON $0008 REG_NUM_BUF_EVENT CON $000C REG_NUM_RX_MISS CON $0010 REG_NUM_TX_COL CON $0012 ' ' Self Control Register ' SELF_CTL_RESET CON $0040 SELF_CTL_HC1E CON $2000 SELF_CTL_HCB1 CON $8000 ' ' Self Status Register ' SELF_ST_INIT_DONE CON $0080 SELF_ST_SI_BUSY CON $0100 SELF_ST_EEP_PRES CON $0200 SELF_ST_EEP_OK CON $0400 SELF_ST_EL_PRES CON $0800 ' ' Bus Control Register ' BUS_CTL_USE_SA CON $0200 BUS_CTL_MEM_MODE CON $0400 BUS_CTL_IOCHRDY CON $1000 BUS_CTL_INT_ENBL CON $8000 ' ' Bus Status Register ' BUS_ST_TX_BID_ERR CON $0080 BUS_ST_RDY4TXNOW CON $0100 ' ' Line Control Register ' LINE_CTL_RX_ON CON $0040 LINE_CTL_TX_ON CON $0080 LINE_CTL_AUI_ONLY CON $0100 LINE_CTL_10BASET CON $0000 ' ' Test Control Register ' ' ' Receiver Configuration Register ' RX_CFG_SKIP CON $0040 RX_CFG_RX_OK_IE CON $0100 RX_CFG_CRC_ERR_IE CON $1000 RX_CFG_RUNT_IE CON $2000 RX_CFG_X_DATA_IE CON $4000 ' ' Receiver Event Register ' RX_EVENT_RX_OK CON $0100 RX_EVENT_IND_ADDR CON $0400 RX_EVENT_BCAST CON $0800 RX_EVENT_CRC_ERR CON $1000 RX_EVENT_RUNT CON $2000 RX_EVENT_X_DATA CON $4000 ' 'Receiver Control Register ' RX_CTL_PROMISCUOUS CON $0080 RX_CTL_RX_OK_A CON $0100 RX_CTL_MCAST_A CON $0200 RX_CTL_IND_A CON $0400 RX_CTL_BCAST_A CON $0800 RX_CTL_CRC_ERR_A CON $1000 RX_CTL_RUNT_A CON $2000 RX_CTL_X_DATA_A CON $4000 ' 'Transmit Configuration Register ' TX_CFG_LOSS_CRS_IE CON $0040 TX_CFG_SQE_ERR_IE CON $0080 TX_CFG_TX_OK_IE CON $0100 TX_CFG_OUT_WIN_IE CON $0200 TX_CFG_JABBER_IE CON $0400 TX_CFG_16_COLL_IE CON $8000 TX_CFG_ALL_IE CON $8FC0 ' 'Transmit Event Register ' TX_EVENT_TX_OK CON $0100 TX_EVENT_OUT_WIN CON $0200 TX_EVENT_JABBER CON $0400 TX_EVENT_16_COLL CON $1000 ' ' Transmit Command Register ' TX_CMD_START_5 CON $0000 TX_CMD_START_381 CON $0080 TX_CMD_START_1021 CON $0040 TX_CMD_START_ALL CON $00C0 TX_CMD_FORCE CON $0100 TX_CMD_ONE_COLL CON $0200 TX_CMD_NO_CRC CON $1000 TX_CMD_NO_PAD CON $2000 ' 'Buffer Configuration Register ' BUF_CFG_SW_INT CON $0040 BUF_CFG_RDY4TX_IE CON $0100 BUF_CFG_TX_UNDR_IE CON $0200 ' ' The IP address and MAC address can be changed to whatever is appropriate ' IP1 CON 128 'first octet of IP address IP2 CON 238 'second octet of IP address IP3 CON 129 'third octet of IP address IP4 CON 88 'fourth octet of IP address MAC1 CON $00 '\ MAC2 CON $00 ' \ MAC3 CON $00 ' \ MAC4 CON $12 ' / 48 bit IEEE OUI (Organizationally Unique Identifier) MAC5 CON $34 ' / MAC6 CON $56 '/ rd CON 4 ' Pin 4 -> EEB read command wr CON 5 ' Pin 5 -> EEB write command aen CON 6 ' Pin 6 -> EEB power_pin CON 7 ' Pin 7 -> Power on/off addrBusOut VAR OUTA ' Address Bus dataBusIn VAR INH ' Data IN Bus dataBusOut VAR OUTH ' Data OUT Bus addr VAR Nib ' Address Nib counter VAR Word ' Counter for main loop i VAR Nib ' Counter in for loop k VAR Nib ' Counter in for loop value VAR Byte packetType VAR Word ' ---- { Temporary storage word } ---- dataW VAR Word dataH VAR dataW.HIGHBYTE dataL VAR dataW.LOWBYTE offsetW VAR Word offsetH VAR offsetW.HIGHBYTE offsetL VAR offsetW.LOWBYTE ' ---- { srcMAC 1--3 locations } ---- srcMAC1_H CON 0 srcMAC1_L CON 1 srcMAC2_H CON 2 srcMAC2_L CON 3 srcMAC3_H CON 4 srcMAC3_L CON 5 ' ---- { Packet Size location } ---- length_H CON 6 length_L CON 7 ' ---- { Control Gain memory locations } ---- P_gain CON 8 D_gain CON 9 ' ---- { Data Buff locations } ---- data_buffer CON 10 ' ---- { srcIP Variables [Necessary for checksum computation] } ---- srcIP1 VAR Word srcIP1H VAR srcIP1.HIGHBYTE srcIP1L VAR srcIP1.LOWBYTE srcIP2 VAR Word srcIP2H VAR srcIP2.HIGHBYTE srcIP2L VAR srcIP2.LOWBYTE '---- { Analog to digital and digital to analog variables and constants } ---- ADres VAR Word 'A-to-D result: one byte. ADresH VAR ADres.HIGHBYTE ADresL VAR ADres.LOWBYTE ADres1 VAR Word 'A-to-D result: one byte. ADresNib0 VAR ADresL.LOWNIB ADresNib1 VAR ADresL.HIGHNIB ADresNib2 VAR ADresH.LOWNIB ADresNib3 VAR ADresH.HIGHNIB ADconfig CON %10000001 ' Configuration for Potentiometer ADconfig2 CON %10010001 ' Configuration for Tachometer AD_CS CON 14 'Chip select is pin 14. AD_Data CON 13 'ADC data output is pin 13. AD_CLK CON 15 'Clock is pin 15. AD_Dout CON 12 'ADC data input is pin 12 DA_CS CON 2 'Chip select is pin 2. DA_CLK CON 0 'Clock is pin 0. DA_DATAOUT CON 1 'input to DAC is pin 1. theta VAR Word temp VAR Word CCPP VAR Word number VAR Byte base CON 10 '---- {Start of the Program} ---- start: HIGH rd HIGH wr HIGH aen DIRH = 0 ' data bus initially input DIRA = %1111 ' address bus is always output GOSUB verChip GOSUB resetChip GOSUB initChip 'DEBUG "Init",CR GOSUB reset_counter read_loop: MAINIO offsetW = ppRxEvt GOSUB readPP 'read the receiver event CCPP = CCPP + 1 IF (CCPP >= 3000) THEN turn_off 'This sequence makes sure that after 1000 times of read_loop, we turn of power amp. IF dataH.BIT0 = 0 THEN read_loop 'it's important to read the following data high byte first addr = portRxTxData+1 GOSUB ioRead 'read and discard status addr = portRxTxData GOSUB ioRead addr = portRxTxData+1 'read and save length in lengthW GOSUB ioRead 'lengthH = value PUT length_H, value addr = portRxTxData GOSUB ioRead 'lengthL = value PUT length_L, value GOSUB recvWord 'srcMAC1W = dataW PUT srcMAC1_H, dataW.HIGHBYTE ' put in EEPROM PUT srcMAC1_L, dataW.LOWBYTE ' put in EEPROM GOSUB recvWord 'srcMAC2W = dataW PUT srcMAC2_H, dataW.HIGHBYTE ' put in EEPROM PUT srcMAC2_L, dataW.LOWBYTE ' put in EEPROM GOSUB recvWord 'srcMAC3W = dataW ' read dest MAC PUT srcMAC3_H, dataW.HIGHBYTE ' put in EEPROM PUT srcMAC3_L, dataW.LOWBYTE ' put in EEPROM GOSUB recvWord 'srcMAC1W = dataW PUT srcMAC1_H, dataW.HIGHBYTE ' put in EEPROM PUT srcMAC1_L, dataW.LOWBYTE ' put in EEPROM GOSUB recvWord 'srcMAC2W = dataW PUT srcMAC2_H, dataW.HIGHBYTE ' put in EEPROM PUT srcMAC2_L, dataW.LOWBYTE ' put in EEPROM GOSUB recvWord 'srcMAC3W = dataW ' read and save source MAC PUT srcMAC3_H, dataW.HIGHBYTE ' put in EEPROM PUT srcMAC3_L, dataW.LOWBYTE ' put in EEPROM GOSUB recvWord 'read the packet type packetType = dataW IF packetType <> $0806 THEN otherType ' This is optional code, I put this in to show how to transmit data. The following responds to the ARP (Address ' Resolution Protocol) request. Someone want to convert an IP address to a MAC destination. We'll check to see ' if the request is valid and if it's for our IP address (192.168.1.2). If so, we send the ARP response along ' with our hardware (MAC) address stored in the constants MAC1 - MAC6 GOSUB recvWord ' next is ar_hwtype (hardware type) IF dataW <> 1 THEN discardAndContinue GOSUB recvWord ' next is ar_prtype (protocol type) IF dataW <> $0800 THEN discardAndContinue GOSUB recvWord ' next is ar_hwlen (hardware address) AND ar_prlen (protocol address length) IF dataH <> 6 THEN discardAndContinue IF dataL <> 4 THEN discardAndContinue GOSUB recvWord ' next is ar_op (ARP operation 1=request, 2=reply) IF dataW <> 1 THEN discardAndContinue GOSUB recvWord ' next is senders hardware address (ar_sha) GOSUB recvWord GOSUB recvWord GOSUB recvWord ' next is senders IP address (ar_spa) srcIP1 = dataW GOSUB recvWord srcIP2 = dataW 'following this is ar_tha and ar_tpa (target mac and IP). We don't care about this since we already know who we are GOSUB dropFrame ' drop the rest GOSUB startTx ' start the transmission dataW = 42 ' length of arp is always 42, the board will pad the runt out GOSUB setTxLen waitTx: offsetW = ppBusSt ' get bus status GOSUB readPP IF dataH.BIT0 = 0 THEN waitTx ' is BUS_ST_RDY4TXNOW (ready for transmit) '1st, send the dest MAC address taken from the src in the arp request 'dataW = srcMAC1W GET srcMAC1_H, dataW.HIGHBYTE GET srcMAC1_L, dataW.LOWBYTE GOSUB sendWord 'dataW = srcMAC2W GET srcMAC2_H, dataW.HIGHBYTE GET srcMAC2_L, dataW.LOWBYTE GOSUB sendWord 'dataW = srcMAC3W GET srcMAC3_H, dataW.HIGHBYTE GET srcMAC3_L, dataW.LOWBYTE GOSUB sendWord dataW = MAC1<<8|MAC2 'now, send our MAC address GOSUB sendWord dataW = MAC3<<8|MAC4 GOSUB sendWord dataW = MAC5<<8|MAC6 GOSUB sendWord dataW = $0806 'packet type = 0806, ARP GOSUB sendWord dataW = 1 'ar_hwtype = 1 GOSUB sendWord dataW = $0800 'ar_prtype = $0800 GOSUB sendWord dataW = $0604 'ar_hwlen = 6, ar_prlen = 4 GOSUB sendWord dataW = 2 'ar_op = 2 (response) GOSUB sendWord dataW = MAC1<<8|MAC2 'ar_sha GOSUB sendWord dataW = MAC3<<8|MAC4 GOSUB sendWord dataW = MAC5<<8|MAC6 GOSUB sendWord dataW = IP1<<8|IP2 'ar_spa GOSUB sendWord dataW = IP3<<8|IP4 GOSUB sendWord 'dataW = srcMAC1W 'ar_tha GET srcMAC1_H, dataW.HIGHBYTE GET srcMAC1_L, dataW.LOWBYTE GOSUB sendWord 'dataW = srcMAC2W GET srcMAC2_H, dataW.HIGHBYTE GET srcMAC2_L, dataW.LOWBYTE GOSUB sendWord 'dataW = srcMAC3W GET srcMAC3_H, dataW.HIGHBYTE GET srcMAC3_L, dataW.LOWBYTE GOSUB sendWord dataW = srcIP1 'ar_tpa GOSUB sendWord dataW = srcIP2 GOSUB sendWord GOTO read_loop otherType: IF packetType <> $0800 THEN discardAndContinue 'filter only IP packets '---- {Decompose the IP header} ---- GOSUB recvWord 'get ip_verlen and ip_tos 'DEBUG "IP Ver ", DEC dataH.HIGHNIB, ", HDR Length=",DEC dataH.LOWNIB*4,", TOS=$",HEX2 dataL,CR GOSUB recvWord 'get packet length 'debug "Packet Length=", dec dataW,cr GOSUB recvWord 'ip_id 'debug "Datagram ID=$", hex4 dataW,cr GOSUB recvWord 'ip_fragoff 'debug "Frag Offset=",dec dataW,cr GOSUB recvWord 'ip_ttl & ip_proto 'debug "TTL=",dec dataH,cr IF dataL <> 17 THEN notUDP 'debug "Protocol=UDP",cr GOTO nextHdrField notUDP: GOTO discardAndContinue nextHdrField: GOSUB recvWord 'ip_cksum 'debug "Checksum=$",hex4 dataW,cr 'debug "Src IP Address=" GOSUB dumpIP2 'debug "Dest IP Address=" GOSUB dumpIP 'lengthW = lengthW - 34 / 2 'subtract the 2 MAC (3 words each) and the protocol type (2 bytes) and the 20 byte header ' dump out the packet data. 'DEBUG "Packet Data:",CR GOSUB recvWord IF dataW = $03E8 THEN next_check GOTO read_loop next_check: FOR i = 0 TO 3 'WE MODIFIED THIS to be 0 to 4 instead of 0 to lengthW GOSUB recvWord checkend: NEXT DEBUG ? dataW IF dataW = $6F6F THEN move_motor '138 is the key, user has to send this in first data byte GOTO read_loop move_motor: AUXIO HIGH power_pin PAUSE 100 MAINIO GOSUB recvWord packetType.LOWBYTE = dataL packetType.HIGHBYTE = dataH IF packetType = $FFFF THEN reset_counter theta = packetType GOSUB recvWord 'DEBUG CR, DEC dataH, "--", DEC dataL, CR ' This recvWord gets Pgain PUT P_gain, dataH ' put in EEPROM PUT D_gain, dataL ' put in EEPROM '---- { PD CONTROL ALGORITHM } ---- AUXIO GOSUB ENCODE_THETA ' From desired command angle, convert to DAC rep. FOR k = 0 TO 1 GOSUB GET_ADC_measurement_pot ' Grab potentiometer ADC Byte representation (rep.) PUT data_buffer+(2*k), ADres.HIGHBYTE PUT data_buffer+(2*k)+1, ADres.LOWBYTE GOSUB DAC_encode ' Convert ADC rep. to DAC rep. GOSUB invert_DAC ' Inverts the potentiometer measurement -theta ADres1 = theta ' Save theta to ADres1 for summation GOSUB sum_DAC ' Takes ADres1 and ADres and does DAC rep. sum GET P_gain, number GOSUB product_DAC ' Products the resulting sum with P gain (takes in number, base, and ADres) temp = ADres ' Temporarily stores the result of product_DAC GOSUB GET_ADC_measurement_tach ' Grab tachometer ADC Byte representation (rep.) GOSUB DAC_encode ' Convert ADC rep. to DAC rep. GET D_gain, number GOSUB product_DAC ' Products the result with P gain (takes in number, base, and ADres) ADres1 = temp ' Save temp to ADres1 for summation GOSUB sum_DAC GOSUB DAC_ADDRESS_ASSIGNMENT ' Takes in ADres and outputs to temp for DAC output GOSUB SEND_DAC_voltage ' Sends temp voltage data to DAC NEXT '---- { END OF PD CONTROL ALGORITHM } ---- MAINIO GOTO sending_packet '----{ SENDING OF PACKET }---- sending_packet: counter = counter + 1 CCPP = 1 'Old way of computing packetType ' packetType = $8679 + srcIP1 + srcIP2 + 3 'packetType variable is being recycled again for holding the checksum ' packetType = $FFFF - packetType 'New way: 'Calculate checksum packetType = $FFFF - $8679 - srcIP1 - srcIP2 - 3 'packetType variable is being recycled again for holding the checksum GOSUB startTx ' start the transmission dataW = $0030 ' Length of entire transmission including link layer data (bytes) GOSUB setTxLen waitTy: offsetW = ppBusSt ' get bus status GOSUB readPP IF dataH.BIT0 = 0 THEN waitTy ' is BUS_ST_RDY4TXNOW (ready for transmit) '1st, send the dest MAC address taken from the src in the arp request 'dataW = srcMAC1W GET srcMAC1_H, dataW.HIGHBYTE GET srcMAC1_L, dataW.LOWBYTE GOSUB sendWord 'dataW = srcMAC2W GET srcMAC2_H, dataW.HIGHBYTE GET srcMAC2_L, dataW.LOWBYTE GOSUB sendWord 'dataW = srcMAC3W GET srcMAC3_H, dataW.HIGHBYTE GET srcMAC3_L, dataW.LOWBYTE GOSUB sendWord dataW = MAC1<<8|MAC2 'now, send our MAC address GOSUB sendWord dataW = MAC3<<8|MAC4 GOSUB sendWord dataW = MAC5<<8|MAC6 GOSUB sendWord dataW = $0800 'packet type = 0800, IP GOSUB sendWord '********* end of ether dataW = $4500 '** IP Version/Header Length (32bit words) GOSUB sendWord dataW = $0022 '*** TOTAL Packet Length (bytes) *** GOSUB sendWord dataW = $0000 '*** ID (if fragment) *** GOSUB sendWord dataW = $4000 '***** FLAGS/OFFSET ***** GOSUB sendWord dataW = $FF11 '***** TTL/PROTOCOL ***** GOSUB sendWord dataW = packetType '******* IP CHKSUM ******* 'MUST BE CHANGED for each different packet or will be droped GOSUB sendWord dataW = $80EE '******* SRC IP 1 ******** GOSUB sendWord dataW = $8158 '******* SRC IP 2 ******** GOSUB sendWord dataW = srcIP1 '******* DEST IP 1 ******* GOSUB sendWord dataW = srcIP2 '******* DEST IP 2 ******* GOSUB sendWord dataW = $03E8 '******** SRC PORT ******* GOSUB sendWord dataW = $03E8 '******* DEST PORT ******* GOSUB sendWord dataW = $000E '******** LENGTH ********* GOSUB sendWord dataW = $0000 '***** UDP CHECKSUM ****** GOSUB sendWord 'dataH = ADres 'CHANGED FROM Error 'dataL = ADres '********* DATA (position reading) ********** FOR k = 0 TO 1 GET data_buffer+(2*k), dataW.HIGHBYTE GET data_buffer+(2*k)+1, dataW.LOWBYTE GOSUB sendWord NEXT dataW = counter '********* DATA (sample number) ********** GOSUB sendWord '------------- END of SENDING OF PACKET ----------------- GOTO read_loop dumpIP: GOSUB recvWord 'DEBUG DEC dataH,".",DEC dataL,"." GOSUB recvWord 'DEBUG DEC dataH,".",DEC dataL,CR RETURN dumpIP2: GOSUB recvWord srcIP1H = dataH srcIP1L = dataL 'DEBUG DEC dataH,".",DEC dataL,"." GOSUB recvWord srcIP2H = dataH srcIP2L = dataL 'DEBUG DEC dataH,".",DEC dataL,CR RETURN discardAndContinue: GOSUB dropFrame GOTO read_loop recvWord: addr = portRxTxData GOSUB ioRead dataH = value addr = portRxTxData+1 GOSUB ioRead dataL = value RETURN ' Sends the transmit start command to the board startTx: dataW = TX_CMD_START_ALL addr = portTxCmd value = dataL GOSUB ioWrite addr = portTxCmd+1 value = dataH GOSUB ioWrite RETURN ' Sends the length of the transmission contained in dataW setTxLen: value = dataL addr = portTxLength GOSUB ioWrite value = dataH addr = portTxLength+1 GOSUB ioWrite RETURN ' Transmits the word at dataW sendWord: addr = portRxTxData value = dataH GOSUB ioWrite addr = portRxTxData+1 value = dataL GOSUB ioWrite RETURN dropFrame: offsetW = ppRxCtl GOSUB readPP dataW = dataW | RX_CFG_SKIP GOSUB writePP RETURN ' ---- {Initializes the CS8900} ---- initChip: offsetW = ppLineCtl dataW = LINE_CTL_10BASET GOSUB writePP ' set to 10BaseT offsetW = $0118 'ppTestCtl con $0118 'Test Control dataW = $4000 GOSUB writePP ' set to full duplex 'no offsetW = ppRxCfg 'irqs dataW = RX_CFG_RX_OK_IE ' gosub writePP offsetW = ppRxCtl dataW = RX_CTL_RX_OK_A|RX_CTL_PROMISCUOUS GOSUB writePP 'no offsetW = ppTxCfg 'irqs dataW = TX_CFG_ALL_IE ' gosub writePP ' ' Important: The IA needs to be byte revered IA=aa:bb:cc:dd:ee:ff ' offsetW = ppIndAddr dataW = MAC2<<8|MAC1 GOSUB writePP offsetW = ppIndAddr+2 dataW = MAC4<<8|MAC3 GOSUB writePP offsetW = ppIndAddr+4 dataW = MAC6<<8|MAC5 GOSUB writePP ' offsetW = ppBusCtl 'no gosub readPP 'irqs dataH.bit7 = 1 ' enable irq ' gosub writePP offsetW = ppLineCtl ' get line control GOSUB readPP dataL.BIT6 = 1 ' SerRxOn dataL.BIT7 = 1 ' SerTxOn GOSUB writePP RETURN ' ---- {Resets the CS8900 and checks to insure initialization done bit is set} ---- resetChip: offsetW = ppSelfCtl dataW = SELF_CTL_RESET GOSUB writePP ' issue a reset to the chip resetWait: PAUSE 1 ' wait 1 millisecond offsetW = ppSelfCtl 'get the Self Control status GOSUB readPP 'debug "ppSelfCtl=",HEX4 dataW,cr IF dataL.BIT6 = 1 THEN resetWait ' bit 6 cleared, chip is reset offsetW = ppSelfSt 'get self status GOSUB readPP 'debug "ppSelfSt=",HEX4 dataW,cr IF dataL.BIT7 = 0 THEN resetWait ' INITD means initialization is done when set 'debug "CS8900 RESET",cr RETURN verChip: ' first, get the signature at portPtr which should be $3x0x addr = portPtr GOSUB ioRead dataL = value addr = portPtr+1 GOSUB ioRead dataH = value IF dataH.HIGHNIB = 3 THEN validChip END validChip: 'DEBUG "Signature=", HEX4 dataW,CR offsetW = $0000 'ppEISA con $0000 'EISA Registration number of CS8900 GOSUB readPP 'DEBUG "EISA=", HEX4 dataW,CR offsetW = ppProdID GOSUB readPP 'DEBUG "ProdID=", HEX4 dataW,CR RETURN ' ---- {Writes the value at dataW to the packet page register at offsetW} ---- writePP: GOSUB setPPPointer addr = portData value = dataL GOSUB ioWrite addr = portData+1 value = dataH GOSUB ioWrite RETURN ' ---- {Read packet page data at offsetW and put result in dataW} ---- readPP: GOSUB setPPPointer addr = portData GOSUB ioRead dataL = value addr = portData+1 GOSUB ioRead dataH = value RETURN ' ---- {Sets the packetpage address} ---- setPPPointer: value = offsetL addr = portPtr GOSUB ioWrite value = offsetH addr = portPtr+1 GOSUB ioWrite RETURN ioRead: DIRH = 0 ' make data bus input addrBusOut = addr LOW aen LOW rd value = dataBusIn HIGH rd HIGH aen RETURN ioWrite: DIRH = %11111111 ' make data bus output dataBusOut = value addrBusOut = addr LOW aen LOW wr HIGH wr HIGH aen RETURN ' ---- {new turn_off function resets the counter after a certain number of read iterations from ethernet} ---- turn_off: temp.HIGHBYTE = %00110111 temp.LOWBYTE = %11111111 AUXIO LOW power_pin GOSUB SEND_DAC_voltage MAINIO reset_counter: counter = 1 CCPP = 1 RETURN '---------------------------- New subroutines --------------------------- '---- { DAC encoding subroutine } ---- DAC_encode: IF (ADres <= 2047) THEN DAC_encode_A IF (ADres > 2047) THEN DAC_encode_B DAC_encode_A: ADres = ADres + 2048 GOTO END_DAC_encode DAC_encode_B: ADres = ADres - 2048 GOTO END_DAC_encode END_DAC_encode: RETURN '---- { End of DAC encoding subroutine } ---- '---- { sum_DAC subroutine, [input: ADres1 and ADres] [output: ADres] } ---- sum_DAC: IF ((ADres1 >= 2048)AND(ADres >= 2048)) THEN sum_DAC_A IF ((ADres1 >= 2048)AND(ADres < 2048)) THEN sum_DAC_B IF ((ADres1 < 2048)AND(ADres < 2048)) THEN sum_DAC_C IF ((ADres1 < 2048)AND(ADres >= 2048)) THEN sum_DAC_D END_sum_DAC: RETURN sum_DAC_A: ADres = 2048 + (ADres1 - 2048) + (ADres - 2048) GOTO END_sum_DAC sum_DAC_B: ADres = 2048 + (ADres1 - 2048) - (2048 - ADres) GOTO END_sum_DAC sum_DAC_C: ADres = 2048 - (2048 - ADres1) - (2048 - ADres) GOTO END_sum_DAC sum_DAC_D: ADres = 2048 - (2048 - ADres1) + (ADres - 2048) GOTO END_sum_DAC '---- { invert DAC value, [input: ADres] [output: ADres] } ---- invert_DAC: ADres = 4095-ADres RETURN '---- { multiply DAC value, [input: ADres, number, base] [output: ADres] } ---- product_DAC: IF (ADres >= 2048) THEN product_DAC_A ' If ADres >= 2048 GOSUB product_DAC_B ' Else go here END_product_DAC: RETURN product_DAC_A: ADres = (number*(ADres - 2048))/base IF ADres >= 2048 THEN product_DAC_A_A ADres = ADres + 2048 GOTO END_product_DAC product_DAC_B: ADres = (number*(2048 - ADres))/base IF ADres >= 2048 THEN product_DAC_B_B ADres = 2048 - ADres GOTO END_product_DAC product_DAC_A_A: ADres = 4095 GOTO END_product_DAC product_DAC_B_B: ADres = 0 GOTO END_product_DAC '---- { encode theta value, [input: theta] [output: theta] } ---- ENCODE_THETA: theta = (41040-(114*theta))/10 IF (theta >=4095) THEN MAX_theta ' Saturation for theta END_theta: RETURN MAX_THETA: theta = 4095 GOTO END_THETA '---- { send DAC voltage data, [input: temp] [output: NONE] } ---- SEND_DAC_voltage: LOW DA_CS 'Activate the DAC SHIFTOUT DA_DATAOUT,DA_CLK,1,[temp.HIGHBYTE] SHIFTOUT DA_DATAOUT,DA_CLK,1,[temp.LOWBYTE] HIGH DA_CS 'Deactivate DAC RETURN '---- { get pot data, [input: none] [output: ADres] } ---- GET_ADC_measurement_pot: LOW AD_CS SHIFTOUT AD_Dout,AD_CLK,MSBPOST,[ADconfig] 'Activate the ADC0831. SHIFTIN AD_Data,AD_CLK,MSBPOST,[ADres\12] 'Shift in the data. HIGH AD_CS 'Deactivate ADC0831. RETURN '---- { get tach data, [input: none] [output: ADres] } ---- GET_ADC_measurement_tach: LOW AD_CS SHIFTOUT AD_Dout,AD_CLK,MSBPOST,[ADconfig2] 'Activate the ADC0831. SHIFTIN AD_Data,AD_CLK,MSBPOST,[ADres\12] 'Shift in the data. HIGH AD_CS 'Deactivate ADC0831. RETURN '---- { Converts voltage data, [input: ADres] [output: temp] } ---- DAC_ADDRESS_ASSIGNMENT: temp.HIGHBYTE.BIT0 = ADres.HIGHBYTE.BIT0 temp.HIGHBYTE.BIT1 = ADres.HIGHBYTE.BIT1 temp.HIGHBYTE.BIT2 = ADres.HIGHBYTE.BIT2 temp.HIGHBYTE.BIT3 = ADres.HIGHBYTE.BIT3 temp.LOWBYTE = ADres.LOWBYTE RETURN