/* Serial Loop By KUMAGAI Masaaki * Rev. 030126 * Rev. 060929 ver 1.0 revised * Rev. 061003 ver 1.1 revised for SL1.1 * * normal Node : * * Configurations: * * SL に使用するSCI * #define SCISL SCI1 * SCI のビットレート設定 * #define SCISLBRR 13 * H8/3048 57600:?, H8/3052 57600:13 115200:6 * ノードレジスタの個数(最大16) * #define REGFILEC 16 * マスタ機能設定 * * 定義するとマスタ動作、かつ、0〜指定した数値-1 のノードを管理可能 * * #define MASTER_RFBSIZE 4 * 機能選択 * #define USE_MEMEXT * メモリ拡張追加 * * #define USE_UIF_H8 * UIF-H8 コンフィグ拡張コマンドサポート * #define USE_BULK * バルク転送 * #define BULKBUFFSIZE %d 領域 * Port の B0を受信割込中に, B1を送信割込中に立てる * #define DEBUGP5 使う * #undef DEBUGP5 (or 略) 使わない * 送信バッファの大きさ * * #define SCIBLENSL 100 * 転送許可 : undef すると転送しない=ループが切れる * #define ENABLE_FORWARD * バースト送受機能 * コマンド番号 * #define BCOM_CMD 0x20 * 全ノード数 * #define BCOM_NNO 5 * 受信レジスタ番号 * #define BCOM_RNO (REGFILEC-1) * 送信レジスタ番号 * #define BCOM_TNO (REGFILEC-1) */ #pragma interrupt(SLSInterrupt) #pragma interrupt(SLRInterrupt) #ifndef SCISL #define SCISL SCI1 #endif #ifndef SCISLBRR #define SCISLBRR 13 #endif #ifndef REGFILEC #define REGFILEC 16 #endif #ifndef SCIBLENSL #define SCIBLENSL 150 #endif #ifdef USE_BULK #ifndef BULKBUFFSIZE #define BULKBUFFSIZE 16 #endif unsigned int BulkBuffer[BULKBUFFSIZE]; #endif void InitializeSCISL(void) { unsigned int i; /* SCI */ SCISL.SCR.BYTE = 0; SCISL.SMR.BYTE = 0; SCISL.BRR = SCISLBRR; for(i=0;i<1000;i++) ; SCISL.SCR.BYTE = 0x30; /* T,R enable */ SCISL.SSR.BYTE &= 0x80; #ifdef DEBUGP5 P5.DDR=0xf; P5.DR.BYTE=0; #endif } typedef struct _SCIBufferSL /* 送信のみバッファリング */ { unsigned char send[SCIBLENSL]; int swp,srp; volatile struct st_sci *sci; } SCIBufferSL; SCIBufferSL scibsl; void ClearSCIBSL(SCIBufferSL *scib) { scib->swp = scib->srp = 0; } int SCIBSLenSL(SCIBufferSL *scib) { if(scib->swp >= scib->srp) return scib->swp-scib->srp; else return scib->swp-scib->srp+SCIBLENSL; } int PutcharSL(SCIBufferSL *scib,char c) { if(SCIBSLenSL(scib)==SCIBLENSL-1) return -1; scib->send[scib->swp]=c; scib->swp++; if(scib->swp>=SCIBLENSL) scib->swp=0; scib->sci->SCR.BIT.TIE=1; /* sci send int enable */ return 0; } int SendCharSL(SCIBufferSL *scib) { if(scib->swp==scib->srp) return 0; scib->sci->TDR=scib->send[scib->srp]; scib->sci->SSR.BIT.TDRE=0; scib->srp++; if(scib->srp>=SCIBLENSL) scib->srp=0; return 1; } #define RBSIZE 258 /* 原理的にこの長さは越えない */ #define PBSIZE SCIBLENSL /* 送信パケットバッファ */ unsigned char recvbuff[RBSIZE]; unsigned char packetbuff[PBSIZE+20]; /* SendPacket との干渉防止に割増 */ int recvc; volatile int packc; int recvmode; int transf; int thisID; char *Profile; unsigned char burstwork[4]; #define RM_START 2 #define RM_SKIP 3 #define RM_RECV 4 #ifdef BCOM_CMD #define RM_BURST 10 #endif volatile unsigned int RegFileS[REGFILEC]; volatile unsigned long RegFileL[REGFILEC]; #ifdef MASTER_RFBSIZE /* master regfile size */ unsigned int NodeRegFileS[MASTER_RFBSIZE][REGFILEC]; unsigned long NodeRegFileL[MASTER_RFBSIZE][REGFILEC]; #endif /* 送信バッファにパケットを置く*/ void PutPacket(void) { int i,pc; unsigned char *p; if((recvc!=0)||(packc==0)) return; if(SCIBSLenSL(&scibsl)>SCIBLENSL-packc) { /* パケット落ち */ packc=0; return; } p=packetbuff; pc=packc; for(i=0;i=SCIBLENSL) scibsl.swp=0; } scibsl.sci->SCR.BIT.TIE=1; /* sci send int enable */ packc=0; return ; } /* 指定パケットを送信する */ int SendPacket(unsigned char *packet,int len) { int i,j; unsigned char *s,*d; if(packc+len>PBSIZE) return 1; /* パケットバッファオーバーフロー */ SCISL.SCR.BIT.RIE=0; /*割込禁止*/ SCISL.SCR.BIT.TIE=0; /*割込禁止*/ s=packet; d=packetbuff+packc; for(i=len;i>0;i--,s++,d++) *d=*s; packc+=len; SCISL.SCR.BIT.RIE=1; /*割込許可*/ SCISL.SCR.BIT.TIE=1; /*割込許可*/ SCISL.SCR.BIT.RIE=0; /*割込禁止*/ SCISL.SCR.BIT.TIE=0; /*割込禁止*/ PutPacket(); SCISL.SCR.BIT.RIE=1; /*割込許可*/ SCISL.SCR.BIT.TIE=1; /*割込許可*/ return 0; } /* =============================================================*/ /* Packet Operation */ /* =============================================================*/ /* source/destination */ #define SLBroadcast 0x80 unsigned char _SLPT[10]; /* =============================*/ /* SL1.1 */ /* =============================*/ #ifdef USESL11 static unsigned char CalculateSL11Sum(unsigned char *d,int l) { int i; unsigned char s=0,x=0; for(i=0;i>8); SLPMakeup(_SLPT,4); SendPacket(_SLPT,SLPHeadLen+4); } void SLSet32(unsigned short dest,unsigned short reg,unsigned long val) { SLDSetup(_SLPT,dest); SLSSetup(_SLPT); /* 0,3 */ _SLPT[SLPConPoint+0]=0x30|(reg&0xf); _SLPT[SLPConPoint+2]=B(val); _SLPT[SLPConPoint+3]=B(val>>8); _SLPT[SLPConPoint+4]=B(val>>16); _SLPT[SLPConPoint+5]=B(val>>24); SLPMakeup(_SLPT,6); SendPacket(_SLPT,SLPHeadLen+6); } void SLReply16(unsigned short dest,unsigned short reg,unsigned short val) { SLDSetup(_SLPT,dest); SLSSetup(_SLPT); /* 0,3 */ _SLPT[SLPConPoint+0]=0x60|(reg&0xf); _SLPT[SLPConPoint+2]=B(val); _SLPT[SLPConPoint+3]=B(val>>8); SLPMakeup(_SLPT,4); SendPacket(_SLPT,SLPHeadLen+4); } void SLReply32(unsigned short dest,unsigned short reg,unsigned long val) { SLDSetup(_SLPT,dest); SLSSetup(_SLPT); /* 0,3 */ _SLPT[SLPConPoint+0]=0x70|(reg&0xf); _SLPT[SLPConPoint+2]=B(val); _SLPT[SLPConPoint+3]=B(val>>8); _SLPT[SLPConPoint+4]=B(val>>16); _SLPT[SLPConPoint+5]=B(val>>24); SLPMakeup(_SLPT,6); SendPacket(_SLPT,SLPHeadLen+6); } void SLGet16(unsigned short dest,unsigned short reg) { SLDSetup(_SLPT,dest); SLSSetup(_SLPT); /* 0,3 */ _SLPT[SLPConPoint+0]=0x40|(reg&0xf); SLPMakeup(_SLPT,2); SendPacket(_SLPT,SLPHeadLen+2); } void SLGet32(unsigned short dest,unsigned short reg) { SLDSetup(_SLPT,dest); SLSSetup(_SLPT); /* 0,3 */ _SLPT[SLPConPoint+0]=0x50|(reg&0xf); SLPMakeup(_SLPT,2); SendPacket(_SLPT,SLPHeadLen+2); } /* =============================================================*/ /* /Packet Operation */ /* =============================================================*/ #ifdef USE_UIF_H8 extern void PacketOperationUIFH8(void); #endif /* 受信したパケットを処理する */ void PacketOperation(void) { unsigned char *p; int i,rid,nd; if(recvc==2) return; /* BCOM はマスタはここで処理する必要あり */ /* */ switch(recvbuff[SLPConPoint]) { case 0x00: /* device reset */ return; case 0x02: /* request Profile */ SLPRepSetDest; packetbuff[packc+SLPConPoint+0]=0x03; packetbuff[packc+SLPConPoint+1]=thisID; for(i=SLPConPoint+2,p=(unsigned char *)Profile;*p;i++,p++) packetbuff[packc+i]=*p; SLPRepSetup(i-SLPConPoint); return; case 0x03: return; } #ifdef USE_MEMEXT if((recvbuff[SLPConPoint]&0xf0)==0x80) /* メモリ拡張コマンド */ { unsigned long addr; unsigned short val; int wf=(recvbuff[SLPConPoint]&1); addr=((unsigned char *)recvbuff)[SLPConPoint+2]|((unsigned int)(recvbuff[SLPConPoint+3])<<8)|((unsigned long)(recvbuff[SLPConPoint+4])<<16); val=wf?((unsigned int)(recvbuff[SLPConPoint+6])<<8):0; /* 16bit */ val|=recvbuff[SLPConPoint+5]; switch(recvbuff[SLPConPoint]) { case 0x80: /* MRead */ case 0x81: SLPRepSetDest; packetbuff[packc+SLPConPoint+0]=0x82|wf; packetbuff[packc+SLPConPoint+1]=thisID; packetbuff[packc+SLPConPoint+2]=recvbuff[SLPConPoint+2]; packetbuff[packc+SLPConPoint+3]=recvbuff[SLPConPoint+3]; packetbuff[packc+SLPConPoint+4]=recvbuff[SLPConPoint+4]; val=wf?(*((unsigned short *)addr)):(*((unsigned char *)addr)); packetbuff[packc+SLPConPoint+5]=val&0xff; packetbuff[packc+SLPConPoint+6]=val>>8; SLPRepSetup(6+wf); return; case 0x82: /* MReply : もらう予定はない */ case 0x83: return; case 0x84: /* MWrite */ *((unsigned char *)addr) = val&0xff; return; case 0x85: *((unsigned short *)addr) = val; return; case 0x86: /* MAnd */ *((unsigned char *)addr) &= val&0xff; return; case 0x87: *((unsigned short *)addr) &= val; return; case 0x88: /* MOr */ *((unsigned char *)addr) |= val&0xff; return; case 0x89: *((unsigned short *)addr) |= val; return; case 0x8a: /* MXor */ *((unsigned char *)addr) ^= val&0xff; return; case 0x8b: *((unsigned short *)addr) ^= val; return; } } #endif /* MEMEXT */ #ifdef USE_UIF_H8 if((recvbuff[2]&0xf0)==0x90) { PacketOperationUIFH8(); return; } #endif #ifdef USE_BULK /* バルク転送 */ if(recvbuff[SLPConPoint]==0xa0) /* bulkset */ { unsigned int *bp; rid=recvbuff[SLPConPoint+2]; nd=recvbuff[SLPConPoint+3]; bp=BulkBuffer+rid; p=recvbuff+SLPConPoint+4; for(i=0;i>8; p[1]=(*bp)&0xff; } SLPRepSetup(4+nd*2); return; } /*if(recvbuff[SLPConPoint]==0xa0) * bulkreply * { なし }*/ #endif if((recvbuff[SLPConPoint]<0x20)||(recvbuff[SLPConPoint]>0x7f)) return; rid=recvbuff[SLPConPoint]&0x0f; if(rid>REGFILEC) rid=REGFILEC-1; switch(recvbuff[SLPConPoint]&0xf0) { case 0x20: /* Set16 */ RegFileS[rid]=((unsigned char *)recvbuff)[SLPConPoint+2]|((unsigned int)(recvbuff[SLPConPoint+3])<<8); return; case 0x30: /* Set32 */ *((unsigned short *)(RegFileL+rid)+1)=((unsigned char *)recvbuff)[SLPConPoint+2]|((unsigned int)(recvbuff[SLPConPoint+3])<<8); *((unsigned short *)(RegFileL+rid)+0)=((unsigned char *)recvbuff)[SLPConPoint+4]|((unsigned int)(recvbuff[SLPConPoint+5])<<8); return; case 0x40: /* Get16 */ SLPRepSetDest; packetbuff[packc+SLPConPoint+0]=0x60|rid; packetbuff[packc+SLPConPoint+1]=thisID; packetbuff[packc+SLPConPoint+2]=*((unsigned char *)(RegFileS+rid)+1); packetbuff[packc+SLPConPoint+3]=*((unsigned char *)(RegFileS+rid)); SLPRepSetup(4); return; case 0x50: /* Get32 */ SLPRepSetDest; packetbuff[packc+SLPConPoint+0]=0x70|rid; packetbuff[packc+SLPConPoint+1]=thisID; packetbuff[packc+SLPConPoint+2]=*((unsigned char *)(RegFileL+rid)+3); packetbuff[packc+SLPConPoint+3]=*((unsigned char *)(RegFileL+rid)+2); packetbuff[packc+SLPConPoint+4]=*((unsigned char *)(RegFileL+rid)+1); packetbuff[packc+SLPConPoint+5]=*((unsigned char *)(RegFileL+rid)+0); SLPRepSetup(6); return; #ifdef MASTER_RFBSIZE /* マスタ動作 */ case 0x60: /* Reply16 */ nd=recvbuff[SLPConPoint+1]&0x3f; /* nd=nd%MASTER_RFBSIZE; */ if(nd>=MASTER_RFBSIZE) return; /* 扱い外 */ NodeRegFileS[nd][rid]=((unsigned char *)recvbuff)[SLPConPoint+2]|((unsigned int)(recvbuff[SLPConPoint+3])<<8); return; case 0x70: /* Reply32 */ nd=recvbuff[SLPConPoint+1]&0x3f; /* nd=nd%MASTER_RFBSIZE; */ if(nd>=MASTER_RFBSIZE) return; /* 扱い外 */ NodeRegFileL[nd][rid]=((unsigned char *)recvbuff)[SLPConPoint+2]|((unsigned int)(recvbuff[SLPConPoint+3])<<8)| ((unsigned long)(recvbuff[SLPConPoint+4])<<16)|((unsigned long)(recvbuff[SLPConPoint+5])<<24); return; #endif } return; } /* 受信した文字をバッファに積むなど処理する */ void SLpackedDecode(unsigned char r) { recvbuff[recvc]=r; if(recvc==0) { recvmode=RM_START; transf=0; /* パケット追加処理 */ /* Sync */ switch(r&0xc0) { case 0x00: if(r==0) { PutcharSL(&scibsl,'\0'); return; } #ifdef BCOM_CMD if(r==BCOM_CMD) { recvmode=RM_BURST; transf=1; *((long *)(burstwork))=RegFileL[BCOM_TNO]; break; } #endif recvmode=RM_SKIP; transf=1; break; case 0xc0: recvmode=RM_SKIP; transf=0; break; case 0x40: if((r&0x3f)==thisID) { recvmode=RM_RECV; transf=0; } else { recvmode=RM_SKIP; transf=1; } break; case 0x80: if((r&0x3f)==thisID) { recvmode=RM_SKIP; transf=0; } /* 自分のは消す */ else { recvmode=RM_RECV; transf=1; } break; } recvc++; return; } recvc++; #ifdef USESL11 #ifndef SL11ML #define SL11ML 48 #endif if((recvbuff[1]>SL11ML)|| ((recvc==3)&&(recvbuff[1]!=((~(recvbuff[2]))&0xff)))) /* パケット長エラー */ { /* リカバは試みない */ recvc=0; packetbuff[packc]=packetbuff[packc+1]=packetbuff[packc+2]=0; packc+=3; /* エラー代わりにnop送ってみる */ return; } #endif if(recvc==recvbuff[1]+SLPHeadLen) /* 長さ */ { if(recvmode==RM_RECV) { PacketOperation(); } /*パケットデコード*/ #ifdef BCOM_CMD if((recvmode==RM_BURST)&&(thisID<=BCOM_NNO)) { RegFileL[BCOM_RNO]=*((long *)(burstwork));} /*バースト終了*/ #endif recvc=0; } return; } /* SCI-SL receive int */ void SLRInterrupt(void) { unsigned char r; int i; #ifdef DEBUGP5 P5.DR.BIT.B0=1; #endif if((SCISL.SSR.BYTE)&0x40) { /* have data */ r=SCISL.RDR; SLpackedDecode(r); #ifdef ENABLE_FORWARD #ifdef BCOM_CMD if(recvmode==RM_BURST) { if(recvc<=2) PutcharSL(&scibsl,r); else if((recvc-3)/4!=thisID-1) PutcharSL(&scibsl,r); else { PutcharSL(&scibsl,burstwork[3-(recvc-3)&(3)]); burstwork[3-(recvc-3)&(3)]=r; } } else #endif if(transf) PutcharSL(&scibsl,r); #else transf=0; /* 転送しないなら随時送信可 */ #endif if((recvc==0)||(transf==0)) PutPacket(); } SCISL.SSR.BYTE &= ~0x78; /* clear flags */ SCISL.SSR.BIT.RDRF=0; SCISL.SCR.BIT.RIE=1; #ifdef DEBUGP5 P5.DR.BIT.B0=0; #endif return ; } /* SCI-SL send int */ void SLSInterrupt(void) { #ifdef DEBUGP5 P5.DR.BIT.B1=1; #endif if(scibsl.srp==scibsl.swp) { SCISL.SCR.BIT.TIE=0; /* sci send int disable */ PutPacket(); } else SendCharSL(&scibsl); #ifdef DEBUGP5 P5.DR.BIT.B1=0; #endif return ; } void InitializeSerialLoop(int ID) { Profile="DefaultName"; ClearSCIBSL(&scibsl); scibsl.sci=&(SCISL); recvc=packc=0; thisID=ID; InitializeSCISL(); SCISL.SCR.BIT.RIE=1; /* sci receive int enable */ PutcharSL(&scibsl,'\0'); } #ifdef USE_UIF_H8 /* * UIF-H8 * */ unsigned int UIFByteCount; void UIFInitializeDevice(void) { int i; /* ポート初期化 */ P6.DR.BIT.B2=1; /* P6-2(nConfig)=H */ PB.DR.BIT.B4=0; /* PB-4(Data)=L */ PB.DR.BIT.B5=0; /* PB-5(Clk)=L */ P6.DDR=0x04; /* P6-1 入力(Status) */ /* P6-2 出力(nConfig) */ P8.DDR=0x00; /* P8-4 入力(ConfDone) */ PB.DDR=0x30; /* PB-4 出力(Data) */ /* PB-5 出力(DClk) */ ITU.TOER.BIT.EXA4=0; /* PB-4 を ITUでつかわない */ ITU.TOER.BIT.EXB4=0; /* PB-5 を ITUでつかわない */ TPC.NDERB.BIT.B12=0; /* PB-4を TPCでつかわない */ TPC.NDERB.BIT.B13=0; /* PB-5を TPCでつかわない */ /* デバイス初期化 */ P6.DR.BIT.B2=0; /* P6-2(nConfig)=H */ for(i=0;i<100;i++) ; P6.DR.BIT.B2=1; /* P6-2(nConfig)=H */ UIFByteCount=0; return; } unsigned char UIFGetStatus(void) { return (P8.DR.BIT.B4?2:0)|(P6.DR.BIT.B1?1:0); } void UIFWriteByte(unsigned char b) { int i; for(i=0;i<8;i++,b=b>>1) { PB.DR.BIT.B5=0; PB.DR.BIT.B4=b&1; PB.DR.BIT.B5=1; } UIFByteCount++; } void UIFWriteBytes(unsigned char *bytes,int c) { unsigned int i,j,n; for(i=0;i>8; packc+=7; } return; } #endif /* USE_UIF_H8 */ /* デバッグ用 packetbuff[packc+0]=0x40|(recvbuff[3]&0x3f); packetbuff[packc+2]=0x03; packetbuff[packc+3]=thisID; packetbuff[packc+4]='A'; packetbuff[packc+1]=3; packc+=5;*/