From b958925f0d4902939666785d168ef542fe2eda17 Mon Sep 17 00:00:00 2001 From: "saoret.one" Date: Sun, 15 Mar 2009 11:11:32 +0000 Subject: [PATCH] morse.b and morse(1) man page. work on devaudio, ethernds.c. --- arm7/audio.c | 42 ++-- arm7/audio.h | 30 ++- arm7/main.c | 1 - clock.c | 9 +- devaudio.c | 106 +++++++-- devnds.c | 35 +-- ethernds.c | 292 +++++++++-------------- fns.h | 8 +- io.h | 6 +- root/appl/nds/guide | 31 +++ root/appl/nds/mkfile | 4 +- root/appl/nds/morse.b | 536 ++++++++++++++++++++++++++++-------------- root/man/1/morse | 148 ++++++++++++ root/man/1/morse.html | 206 ++++++++++++++++ root/man/mkfile | 6 + root/man/mkman | 17 ++ sds | 1 + trap.c | 2 +- 18 files changed, 1031 insertions(+), 449 deletions(-) create mode 100644 root/appl/nds/guide create mode 100644 root/man/1/morse create mode 100644 root/man/1/morse.html create mode 100644 root/man/mkfile create mode 100644 root/man/mkman diff --git a/arm7/audio.c b/arm7/audio.c index 242d560..1e4850d 100644 --- a/arm7/audio.c +++ b/arm7/audio.c @@ -47,11 +47,21 @@ recintr(void *a) TxSound *snd = a; //print("snd7 %lx %lx %lx\n", (ulong)snd, (ulong)snd->d, snd->n); - if(snd->d && nrs++ < snd->n){ - if(snd->fmt) - ((ushort*)snd->d)[nrs] = mic_read(Tscgetmic12); - else + if(snd->inuse && nrs++ < snd->n){ + switch(snd->flags & (AFlagsigned|AFlag8bit)){ + case (AFlag8bit): ((uchar*)snd->d)[nrs] = mic_read(Tscgetmic8); + break; + case (AFlagsigned|AFlag8bit): + ((uchar*)snd->d)[nrs] = mic_read(Tscgetmic8) ^ 0x80; + break; + case (AFlagsigned): + ((ushort*)snd->d)[nrs] = (mic_read(Tscgetmic12) - 2048) << 4; // ^ 0x8000; + break; + default: + ((ushort*)snd->d)[nrs] = mic_read(Tscgetmic12); + break; + } }else audiorec(snd, 0); @@ -63,19 +73,21 @@ audiorec(TxSound *snd, int on) { TimerReg *t = TMRREG + AUDIOtimer; - if(!snd) + if(!snd || snd->d == nil) return 0; if(on){ nrs = 0; + snd->inuse = 1; + t->data = TIMER_BASE(Tmrdiv1) / snd->rate; t->ctl = Tmrena | Tmrdiv1 | Tmrirq; intrenable(TIMERAUDIObit, recintr, snd, 0); }else{ t->ctl &= ~Tmrena; intrmask(TIMERAUDIObit, 0); - - snd->d = nil; + + snd->inuse = 0; return nrs; } } @@ -90,17 +102,17 @@ audioplay(TxSound *snd, int on) schan = SCHANREG + snd->chan; schan->rpt = 0; - schan->tmr = SCHAN_BASE / (int)snd->rate; + schan->tmr = SCHAN_BASE / snd->rate; schan->src = (ulong) snd->d; - schan->wlen = snd->fmt? snd->n>>2: snd->n>>1; + schan->wlen = snd->flags & AFlag8bit? snd->n>>1: snd->n>>2; schan->cr.vol = snd->vol; schan->cr.pan = snd->pan; - schan->cr.ctl |= SCena | SCrep1shot | (snd->fmt? SCpcm16bit: SCpcm8bit); + schan->cr.ctl |= SCena | SCrep1shot | (snd->flags & AFlag8bit? SCpcm8bit: SCpcm16bit); return 1; } void -audiopower(int dir, int on) +audiopower(int dir, int l) { uchar pwr; @@ -109,7 +121,7 @@ audiopower(int dir, int on) default: break; case F9Aupowerout: - if(on){ + if(l){ POWERREG->pcr |= 1<cr.ctl = Sndena | Maxvol; SNDREG->bias = 0x200; @@ -121,16 +133,16 @@ audiopower(int dir, int on) } break; case F9Aupowerin: - if(on){ + if(l){ power_write(POWER_CONTROL, pwr | POWER_SOUND_AMP); power_write(POWER_MIC_AMPL, POWER_MIC_AMPLON); - power_write(POWER_MIC_GAIN, POWER_MIC_GAIN_20); + power_write(POWER_MIC_GAIN, l); }else{ power_write(POWER_CONTROL, pwr & ~POWER_SOUND_AMP); power_write(POWER_MIC_AMPL, POWER_MIC_AMPLOFF); - power_write(POWER_MIC_GAIN, POWER_MIC_GAIN_20); + power_write(POWER_MIC_GAIN, l); } break; } diff --git a/arm7/audio.h b/arm7/audio.h index 9e32a21..267bf22 100644 --- a/arm7/audio.h +++ b/arm7/audio.h @@ -68,20 +68,34 @@ struct SndReg { enum { Sndena = 1<<15, + + /* TxSound.flags: */ + AFlagin = 1<<0, /* direction: audio in/out */ + AFlag8bit = 1<<1, /* sample size: 8 bit/16 bit (1/0) */ + AFlagsigned = 1<<2, /* sample sign: signed/unsigned */ + AFlagmono = 1<<3, /* sample chans: mono/stereo */ + + /* encoding */ + AFlagpcm = 1<<4, + AFlagadpcm = 1<<5, + AFlagpsg = 1<<6, }; typedef struct TxSound TxSound; struct TxSound { - void *d; /* data samples */ - ulong n; /* samples number */ - ulong rate; /* rate (hz) */ + ushort inuse; + ushort flags; /* audio flags */ + TxSound *phys; /* uncached self-ptr to this TxSound */ + + void *d; /* data samples */ + ulong n; /* samples number */ + long rate; /* rate (hz) */ - uchar chan; /* SCHANREG channel */ - uchar vol; - uchar pan; - uchar fmt; /* pcm8bit/pcm16bit (0/1) */ + uchar vol; /* volume */ + uchar pan; /* panning */ + uchar chan; /* SCHANREG channel */ }; int audiorec(TxSound *snd, int on); int audioplay(TxSound *snd, int on); -void audiopower(int dir, int on); +void audiopower(int dir, int level); diff --git a/arm7/main.c b/arm7/main.c index 2ce7595..0303e07 100644 --- a/arm7/main.c +++ b/arm7/main.c @@ -49,7 +49,6 @@ fiforecvintr(void*) { ulong v, vv; uchar ndstype[1]; - TxSound *snd; int power, ier; while(!(FIFOREG->ctl & FifoRempty)) { diff --git a/clock.c b/clock.c index 087bd6d..8f5b5e9 100644 --- a/clock.c +++ b/clock.c @@ -167,19 +167,19 @@ ulong _mularsv(ulong m0, ulong m1, ulong a, ulong s); #define MULDIVR64(x,a,b,n) ((ulong)_mularsv(x, FXDPTDIVR(a,b,n), 1<<((n)-1), (n))) -ushort +static ushort timer_start(void) { return TMRREG->data; } -ushort +static ushort timer_ticks(ulong t0) { return TMRREG->data - t0; } -void +static void timer_delay(int t) { ulong t0 = timer_start(); @@ -190,11 +190,10 @@ timer_delay(int t) void microdelay(int us) { - ulong t = US2TMR(t); + ulong t = US2TMR(us); timer_delay(t); } - void delay(int ms) { diff --git a/devaudio.c b/devaudio.c index 6417c2f..ca0cff0 100644 --- a/devaudio.c +++ b/devaudio.c @@ -21,10 +21,13 @@ enum Qaudioctl, Fmono = 1, - Fin = 2, + Fin = 2, Fout = 4, F16bits = 8, - + Fpcm = 16, + Fadpcm = 32, + Fpsg = 64, + Aclosed = 0, Aread, Awrite, @@ -91,10 +94,9 @@ static struct static char Emode[] = "illegal open mode"; static char Evolume[] = "illegal volume specifier"; -/* TODO: use the 16 sound channels available */ -static int chan = 1; /* audio sound channel */ -static TxSound Snd[NSChannels+1]; /* play and record */ -static TxSound* snd[NSChannels+1]; +static TxSound mixer; /* mxvolume */ +static TxSound record; /* recording */ +static TxSound snd[NSChannels]; /* playing */ static void mxvolume(void) @@ -104,31 +106,78 @@ mxvolume(void) rov = audio.rovol[Vaudio]; lov = audio.lovol[Vaudio]; - snd[chan]->chan = (audio.flags & Fmono? 1: 2); - snd[chan]->rate = audio.lovol[Vspeed]; - snd[chan]->vol = (Maxvol - Minvol) * (lov + rov) / (2*100); - snd[chan]->pan = (Maxvol - Minvol) * rov / (2*lov+1); - snd[chan]->fmt = audio.flags & F16bits; + mixer.rate = audio.lovol[Vspeed]; + mixer.vol = (Maxvol - Minvol) * (lov + rov) / (2*100); + mixer.pan = (Maxvol - Minvol) * rov / (2*lov+1); + + if(audio.flags & Fpcm) + mixer.flags |= AFlagpcm; + else if(audio.flags & Fadpcm) + mixer.flags |= AFlagadpcm; + else if(audio.flags & Fpsg) + mixer.flags &= ~AFlagpsg; + + if(audio.flags & Fmono) + mixer.flags |= AFlagmono; + else + mixer.flags &= ~AFlagmono; + + if(audio.flags & F16bits) + mixer.flags &= ~AFlag8bit; + else + mixer.flags |= AFlag8bit; +} + +static int +getchannel(void) +{ + int i; + + for(i=0; id = d; - snd[chan]->n = n; - snd[chan]->chan = chan; - fifoput(F9TAudio|F9Auplay, (ulong)snd[chan]); + int i; + + if((i=getchannel()) == -1) + error(Einuse); + DPRINT("#A: play %d\n", i); + memmove(&snd[i], &mixer, sizeof(TxSound)); + snd[i].phys = (TxSound*)uncached(&snd[i]); + //snd[i].phys->inuse = 1; + snd[i].phys->d = d; + snd[i].phys->n = n; + snd[i].phys->chan = i; + fifoput(F9TAudio|F9Auplay, (ulong)snd[i].phys); +} + +static int +recording(void *a) +{ +// tsleep(&up->sleep, recording, &record, 100); + TxSound *snd = (TxSound*)a; + return snd->inuse; } static void recaudio(void* d, ulong n) { - memmove(snd[0], snd[chan], sizeof(TxSound)); - snd[0]->d = d; - snd[0]->n = n; - fifoput(F9TAudio|F9Aurec, (ulong)snd[0]); - while(snd[0]->d != nil) - ; + while(record.inuse); + DPRINT("i %x r %d f %x\n", record.inuse, record.rate, record.flags); + memmove(&record, &mixer, sizeof(TxSound)); + record.phys = (TxSound*)uncached(&record); + record.phys->d = d; + record.phys->n = n; + fifoput(F9TAudio|F9Aurec, (ulong)record.phys); + while(record.inuse); } static void @@ -152,8 +201,8 @@ audioinit(void) audio.amode = Aclosed; resetlevel(); - for(i=0; i< NSChannels+1; i++) - snd[i] = (TxSound*)uncached(&Snd[i]); + for(i=0; i< NSChannels; i++) + snd[i].phys = (TxSound*)uncached(&snd[i]); } static Chan* @@ -257,7 +306,7 @@ audioclose(Chan *c) } if (audio.amode == 0) { /* turn audio off */ - DPRINT("#A: audio off"); + DPRINT("#A: audio off\n"); //fifoput(F9TAudio|F9Aupowerin, 0); //fifoput(F9TAudio|F9Aupowerout, 0); } @@ -288,6 +337,7 @@ audioread(Chan *c, void *v, long n, vlong offset) buf[0] = 0; s = buf; e = buf + sizeof(buf); + // TODO add encoding for(m=0; volumes[m].name; m++){ liv = audio.livol[m]; riv = audio.rivol[m]; @@ -394,7 +444,13 @@ audiowrite(Chan *c, void *vp, long n, vlong) if(strcmp(field[i], "enc") == 0) { if(++i >= nf) error(Evolume); - if(strcmp(field[i], "pcm") != 0) + if(strcmp(field[i], "pcm") == 0) + audio.flags |= Apcm; + else if(strcmp(field[i], "adpcm") == 0) + audio.flags |= Aadpcm; + else if(strcmp(field[i], "psg") == 0) + audio.flags |= Apsg; + else error(Evolume); goto cont0; } diff --git a/devnds.c b/devnds.c index 9595295..24e225d 100644 --- a/devnds.c +++ b/devnds.c @@ -16,7 +16,6 @@ enum { Qdir, Qctl, - Qinfo, Qfw, Qrom, Qsram, @@ -27,7 +26,6 @@ static Dirtab ndstab[]={ ".", {Qdir, 0, QTDIR}, 0, 0555, "ndsctl", {Qctl}, 0, 0600, - "ndsinfo", {Qinfo}, 0, 0600, "ndsfw", {Qfw}, 0, 0400, "ndsrom", {Qrom}, 0, 0600, "ndssram", {Qsram}, 0, 0600, @@ -217,7 +215,7 @@ static long ndsread(Chan* c, void* a, long n, vlong offset) { char *tmp, *p, *e; - int v, t, temp, len; + int temp, len; UserInfo *pu = UINFOREG; uchar *pa; uchar b; @@ -239,26 +237,6 @@ ndsread(Chan* c, void* a, long n, vlong offset) case Qdir: return devdirread(c, a, n, ndstab, nelem(ndstab), devgen); - case Qinfo: - tmp = malloc(READSTR); - if(waserror()){ - free(tmp); - nexterror(); - } - fifoput(F9TSystem|F9Sysrtmp, (ulong)uncached(&temp)); - snprint(tmp, READSTR, - "ds type: %x %s\n" - "battery: %d %s\n" - "temp (%d): %d.%.2d\n", - 1, (1? "ds" : "ds-lite"), - 0, (0? "low" : "high"), - temp, temp>>12, temp & ((1<<13) -1)); - - n = readstr(offset, a, n, tmp); - poperror(); - free(tmp); - break; - case Qfw: tmp = p = malloc(READSTR); if(waserror()) { @@ -273,7 +251,7 @@ ndsread(Chan* c, void* a, long n, vlong offset) p = seprint(p, e, "alarm %s [%.2d:%.2d]\n", pu->alarmon? "on": "off", pu->alarmhour, pu->alarmmin); p = seprint(p, e, "adc t1 (%d,%d) t2 (%d,%d)\n", pu->adc.x1, pu->adc.y1, pu->adc.x2, pu->adc.y2); p = seprint(p, e, "scr t1 (%d,%d) t2 (%d,%d)\n", pu->adc.xpx1, pu->adc.ypx1, pu->adc.xpx2, pu->adc.ypx2); - p = seprint(p, e, "flags (0x%lux) lang %s: %s %s %s\n", + p = seprint(p, e, "flags (0x%ux) lang %s: %s %s %s\n", pu->flags, langlst[pu->flags&Langmask], (pu->flags & Gbalowerscreen)? "gbalowerscreen": "", @@ -281,6 +259,15 @@ ndsread(Chan* c, void* a, long n, vlong offset) (pu->flags & Nosettings)? "nosettings": ""); p = seprint(p, e, "blight %d\n", (pu->flags>>Blightshift)&Blightmask); + fifoput(F9TSystem|F9Sysrtmp, (ulong)uncached(&temp)); + p = seprint(p, e, + "ds type: %x %s\n" + "battery: %d %s\n" + "temp (%d): %d.%.2d\n", + 1, (1? "ds" : "ds-lite"), + 0, (0? "low" : "high"), + temp, temp>>12, temp & ((1<<13) -1)); + n = readstr(offset, a, n, tmp); poperror(); free(tmp); diff --git a/ethernds.c b/ethernds.c index 981c635..1843728 100644 --- a/ethernds.c +++ b/ethernds.c @@ -112,6 +112,43 @@ WifiSyncHandler synchandler = 0; #define Spinlock_Acquire(arg) SPINLOCK_OK #define Spinlock_Release(arg) +void ethhdr_print(char f, void * d) { + Etherpkt *p = d; + + print("%c:%x%x%x%x%x%x %x%x%x%x%x%x %x%x\n", + f, + p->d[0], p->d[1], p->d[2], p->d[3], p->d[4], p->d[5], + p->s[0], p->s[1], p->s[2], p->s[3], p->s[4], p->s[5], + p->type[0], p->type[1]); +} + +static char* +dump_pkt(uchar *data, ushort len) +{ + uchar *c; + static char buff[2024]; + char *c2; + + c = data; + c2 = buff; + while ((c - data) < len) { + if (((*c) >> 4) > 9) + *(c2++) = ((*c) >> 4) - 10 + 'A'; + else + *(c2++) = ((*c) >> 4) + '0'; + + if (((*c) & 0x0f) > 9) + *(c2++) = ((*c) & 0x0f) - 10 + 'A'; + else + *(c2++) = ((*c) & 0x0f) + '0'; + c++; + if ((c - data) % 2 == 0) + *(c2++) = ' '; + } + *c2 = '\0'; + return buff; +} + void Wifi_CopyMacAddr(volatile void * dest, volatile void * src) { ((u16 *)dest)[0]=((u16 *)src)[0]; ((u16 *)dest)[1]=((u16 *)src)[1]; @@ -141,6 +178,24 @@ void Wifi_TxBufferWrite(s32 start, s32 len, u16 * data) { } } +int Wifi_RxRawReadPacket(s32 packetID, s32 readlength, u16 * data) { + int readlen,read_data; + readlength= (readlength+1)/2; + read_data=0; + while(readlength>0) { + readlen=readlength; + if(readlen>(WIFI_RXBUFFER_SIZE/2)-packetID) readlen=(WIFI_RXBUFFER_SIZE/2)-packetID; + readlength-=readlen; + read_data+=readlen; + while(readlen>0) { + *(data++) = WifiData->rxbufData[packetID++]; + readlen--; + } + packetID=0; + } + return read_data; +} + u16 Wifi_RxReadOffset(s32 base, s32 offset) { base+=offset; if(base>=(WIFI_RXBUFFER_SIZE/2)) base -= (WIFI_RXBUFFER_SIZE/2); @@ -174,7 +229,7 @@ void Wifi_RawSetPacketHandler(WifiPacketHandler wphfunc) { packethandler=wphfunc; } void Wifi_SetSyncHandler(WifiSyncHandler wshfunc) { - synchandler=wshfunc; + synchandler=wshfunc; } void Wifi_DisableWifi(void) { @@ -513,17 +568,15 @@ void Wifi_Update(void) { base = WifiData->rxbufIn; len=Wifi_RxReadOffset(base,4); fulllen=((len+3)&(~3))+12; -#ifdef WIFI_USE_TCP_SGIP // Do lwIP interfacing for rx here if((Wifi_RxReadOffset(base,6)&0x01CF)==0x0008) // if it is a non-null data packet coming from the AP (toDS==0) { u16 framehdr[6+12+2+4]; - sgIP_memblock * mb; int hdrlen; base2=base; Wifi_RxRawReadPacket(base,22*2,framehdr); - // ethhdr_print('!',framehdr+8); + ethhdr_print('!',framehdr+8); if((framehdr[8]==((u16 *)WifiData->MacAddr)[0] && framehdr[9]==((u16 *)WifiData->MacAddr)[1] && framehdr[10]==((u16 *)WifiData->MacAddr)[2]) || (framehdr[8]==0xFFFF && framehdr[9]==0xFFFF && framehdr[10]==0xFFFF)) { // destination matches our mac address, or the broadcast address. @@ -534,6 +587,9 @@ void Wifi_Update(void) { //} // SGIP_DEBUG_MESSAGE(("%04X %04X %04X %04X %04X",Wifi_RxReadOffset(base2-8,0),Wifi_RxReadOffset(base2-7,0),Wifi_RxReadOffset(base2-6,0),Wifi_RxReadOffset(base2-5,0),Wifi_RxReadOffset(base2-4,0))); // check for LLC/SLIP header... + +#ifdef WIFI_USE_TCP_SGIP + sgIP_memblock * mb; if(Wifi_RxReadOffset(base2-4,0)==0xAAAA && Wifi_RxReadOffset(base2-4,1)==0x0003 && Wifi_RxReadOffset(base2-4,2)==0) { mb = sgIP_memblock_allocHW(14,len-8-hdrlen); if(mb) { @@ -555,10 +611,10 @@ void Wifi_Update(void) { } } +#endif } } -#endif // check if we have a handler if(packethandler) { @@ -575,29 +631,29 @@ void Wifi_Update(void) { } } -/* -int Wifi_TransmitFunction(sgIP_memblock * mb) { +/* modified to fit devether.c interface */ +int Wifi_TransmitFunction(Block * b) { // convert ethernet frame into wireless frame and output. // ethernet header: 6byte dest, 6byte src, 2byte protocol_id // assumes individual pbuf len is >=14 bytes, it's pretty likely ;) - also hopes pbuf len is a multiple of 2 :| int base,framelen, hdrlen, writelen; - int copytotal, copyexpect; + int copytotal, copyexpect; u16 framehdr[6+12+2]; - sgIP_memblock * t; - framelen=mb->totallength-14+8 + (WifiData->wepmode7?4:0); - - if(!(WifiData->flags9&WFLAG_ARM9_NETUP)) { - SGIP_DEBUG_MESSAGE(("Transmit:err_netdown")); - sgIP_memblock_free(mb); - return 0; //? - } + Block * t; + framelen=BLEN(b)-14+8 + (WifiData->wepmode7?4:0); + + if(!(WifiData->flags9&WFLAG_ARM9_NETUP)) { + DPRINT(("Transmit:err_netdown")); + freeb(b); + return 0; //? + } if(framelen+40>Wifi_TxBufferWordsAvailable()*2) { // error, can't send this much! - SGIP_DEBUG_MESSAGE(("Transmit:err_space")); - sgIP_memblock_free(mb); + DPRINT(("Transmit:err_space")); + freeb(b); return 0; //? } - ethhdr_print('T',mb->datastart); + ethhdr_print('T',b->rp); framehdr[0]=0; framehdr[1]=0; framehdr[2]=0; @@ -610,21 +666,21 @@ int Wifi_TransmitFunction(sgIP_memblock * mb) { framehdr[6]=0x0008; Wifi_CopyMacAddr(framehdr+14,WifiData->bssid7); Wifi_CopyMacAddr(framehdr+11,WifiData->MacAddr); - Wifi_CopyMacAddr(framehdr+8,((u8 *)mb->datastart)); + Wifi_CopyMacAddr(framehdr+8,((u8 *)b->rp)); } else { framehdr[6]=0x0108; Wifi_CopyMacAddr(framehdr+8,WifiData->bssid7); Wifi_CopyMacAddr(framehdr+11,WifiData->MacAddr); - Wifi_CopyMacAddr(framehdr+14,((u8 *)mb->datastart)); + Wifi_CopyMacAddr(framehdr+14,((u8 *)b->rp)); } if(WifiData->wepmode7) { framehdr[6] |=0x4000; hdrlen=20; } framehdr[17] = 0; framehdr[18] = 0; // wep IV, will be filled in if needed on the arm7 side. framehdr[19] = 0; - framehdr[5]=framelen+hdrlen*2-12+4; - copyexpect= ((framelen+hdrlen*2-12+4) +12 -4 +1)/2; - copytotal=0; + framehdr[5]=framelen+hdrlen*2-12+4; + copyexpect= ((framelen+hdrlen*2-12+4) +12 -4 +1)/2; + copytotal=0; WifiData->stats[WSTAT_TXQUEUEDPACKETS]++; WifiData->stats[WSTAT_TXQUEUEDBYTES]+=framelen+hdrlen*2; @@ -632,52 +688,53 @@ int Wifi_TransmitFunction(sgIP_memblock * mb) { base = WifiData->txbufOut; Wifi_TxBufferWrite(base,hdrlen,framehdr); base += hdrlen; - copytotal+=hdrlen; + copytotal+=hdrlen; if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2; // add LLC header framehdr[0]=0xAAAA; framehdr[1]=0x0003; framehdr[2]=0x0000; - framehdr[3]=((u16 *)mb->datastart)[6]; // frame type + framehdr[3]=((u16 *)b->rp)[6]; // frame type Wifi_TxBufferWrite(base,4,framehdr); base += 4; - copytotal+=4; + copytotal+=4; if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2; - t=mb; - writelen=(mb->thislength-14); + t=b; + writelen=(BLEN(b)-14); if(writelen) { - Wifi_TxBufferWrite(base,(writelen+1)/2,((u16 *)mb->datastart)+7); + Wifi_TxBufferWrite(base,(writelen+1)/2,((u16 *)b->rp)+7); base+=(writelen+1)/2; - copytotal+=(writelen+1)/2; + copytotal+=(writelen+1)/2; if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2; } - while(mb->next) { - mb=mb->next; - writelen=mb->thislength; - Wifi_TxBufferWrite(base,(writelen+1)/2,((u16 *)mb->datastart)); +/* + while(b->next) { + b=b->next; + writelen=BLEN(b); + Wifi_TxBufferWrite(base,(writelen+1)/2,((u16 *)b->rp)); base+=(writelen+1)/2; - copytotal+=(writelen+1)/2; + copytotal+=(writelen+1)/2; + if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2; + } +*/ + if(WifiData->wepmode7) { // add required extra bytes + base+=2; + copytotal+=2; if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2; } - if(WifiData->wepmode7) { // add required extra bytes - base+=2; - copytotal+=2; - if(base>=(WIFI_TXBUFFER_SIZE/2)) base -= WIFI_TXBUFFER_SIZE/2; - } WifiData->txbufOut=base; // update fifo out pos, done sending packet. - sgIP_memblock_free(t); // free packet, as we're the last stop on this chain. + freeb(t); // free packet, as we're the last stop on this chain. - if(copytotal!=copyexpect) { - SGIP_DEBUG_MESSAGE(("Tx exp:%i que:%i",copyexpect,copytotal)); - } - if(synchandler) synchandler(); - return 0; + if(copytotal!=copyexpect) { + DPRINT("Tx exp:%d que:%d\n",copyexpect,copytotal); + } + if(synchandler) synchandler(); + return 0; } -*/ static const char * ASSOCSTATUS_STRINGS[] = { [ASSOCSTATUS_DISCONNECTED] = "disconnected", // not *trying* to connect @@ -950,64 +1007,6 @@ attach(Ether *ether) } } -static char* -dump_pkt(uchar *data, ushort len) -{ - uchar *c; - static char buff[2024]; - char *c2; - - c = data; - c2 = buff; - while ((c - data) < len) { - if (((*c) >> 4) > 9) - *(c2++) = ((*c) >> 4) - 10 + 'A'; - else - *(c2++) = ((*c) >> 4) + '0'; - - if (((*c) & 0x0f) > 9) - *(c2++) = ((*c) & 0x0f) - 10 + 'A'; - else - *(c2++) = ((*c) & 0x0f) + '0'; - c++; - if ((c - data) % 2 == 0) - *(c2++) = ' '; - } - *c2 = '\0'; - return buff; -} - -static void -txloadpacket(Ether *ether) -{ - Ctlr *ctlr; - Block *b; - int lenb; - - ctlr = ether->ctlr; - b = ctlr->waiting; - ctlr->waiting = nil; - if(b == nil) - return; // shouldn't happen -/* - // only transmit one packet at a time - lenb = BLEN(b); - - // wrap up packet information and send it to arm7 - memmove((void *)ctlr->txpktbuf, b->rp, lenb); - ctlr->txpkt.len = lenb; - ctlr->txpkt.data = (void *)ctlr->txpktbuf; - freeb(b); - - if(1)print("dump txpkt[%lud] @ %lux:\n%s", - (ulong)ctlr->txpkt.len, ctlr->txpkt.data, - dump_pkt((uchar*)ctlr->txpkt.data, ctlr->txpkt.len)); - - // write data to memory before ARM7 gets hands on - dcflush(&ctlr->txpkt, sizeof(ctlr->txpkt)); -*/ -} - static void txstart(Ether *ether) { @@ -1020,7 +1019,7 @@ txstart(Ether *ether) if((ctlr->waiting = qget(ether->oq)) == nil) break; /* ctlr->waiting is a new block to transmit: allocate space */ - txloadpacket(ether); + Wifi_TransmitFunction(ctlr->waiting); } } @@ -1029,70 +1028,6 @@ enum { WF_Fromds = 0x0200, }; -static void -rxstart(Ether *ether) -{ - static uchar bcastaddr[Eaddrlen] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - Wifi_RxHeader *rx_hdr; - WFrame *f; - Ctlr *ctlr; - Block* bp; - Etherpkt* ep; - - if (ether->ctlr == nil) - return; - - ctlr = ether->ctlr; -/* - // invalidate cache before we read data written by ARM7 - dcflush(&ctlr->rxpkt, sizeof(ctlr->rxpkt)); - - if(1)print("dump rxpkt[%lud] @ %lux:\n%s", - (ulong)ctlr->rxpkt.len, ctlr->rxpkt.data, - dump_pkt((uchar*)ctlr->rxpkt.data, ctlr->rxpkt.len)); - - rx_hdr = (Wifi_RxHeader*)(uchar*)&ctlr->rxpkt + 2; - f = (WFrame *)(uchar*)&ctlr->rxpkt + 2; - - if ((f->framectl & 0x01CF) == WF_Data) { - if (memcmp(ether->ea, f->addr1, Eaddrlen) == 0 - || memcmp(ether->ea, bcastaddr, Eaddrlen) == 0){ - - // hdrlen == 802.11 header length bytes - int base2, hdrlen; - base2 = 22; - hdrlen = 24; - // looks like WEP IV and IVC are removed from RX packets - - // check for LLC/SLIP header... - if (((ushort *) rx_hdr)[base2 - 4 + 0] == 0xAAAA - && ((ushort *) rx_hdr)[base2 - 4 + 1] == 0x0003 - && ((ushort *) rx_hdr)[base2 - 4 + 2] == 0) { - // mb = sgIP_memblock_allocHW(14,len-8-hdrlen); - // Wifi_RxRawReadPacket(base2,(len-8-hdrlen)&(~1),((u16 *)mb->datastart)+7); - int len = rx_hdr->byteLength; - bp = iallocb(ETHERHDRSIZE + len - 8 + hdrlen + 2); - if (!bp) - return; - - ep = (Etherpkt*) bp->wp; - memmove(ep->d, f->addr1, Eaddrlen); - if (f->framectl & WF_Fromds) - memmove(ep->s, f->addr3, Eaddrlen); - else - memmove(ep->s, f->addr2, Eaddrlen); - - memmove(ep->type,&f->type,2); - bp->wp = bp->rp+(ETHERHDRSIZE+f->dlen); - - etheriq(ether, bp, 1); - } - } - - } -*/ -} - static void transmit(Ether *ether) { @@ -1117,19 +1052,8 @@ interrupt(Ureg*, void *arg) ctlr = ether->ctlr; if (ctlr == nil) return; - - /* IPCSYNC irq: - * used by arm7 to notify the arm9 - * that there's wifi activity (tx/rx) - */ - type = IPCREG->ctl & Ipcdatain; - ilock(ctlr); - if (type == I7WFrxdone) - rxstart(ether); - else if (type == I7WFtxdone) - print("txdone\n"); - intrclear(ether->irq, 0); - iunlock(ctlr); + + /* could call Wifi_Update */ } /* set scanning interval */ diff --git a/fns.h b/fns.h index 4cf8398..6933062 100644 --- a/fns.h +++ b/fns.h @@ -65,16 +65,10 @@ ulong witcm(ulong); #define KADDR(p) ((void *) p) #define PADDR(v) va2pa((void*)(v)) -ushort timer_start(void); -ushort timer_ticks(ulong); -void timer_delay(int ost); -ulong ms2tmr(int ms); -int tmr2ms(ulong t); void delay(int ms); -ulong us2tmr(int us); -int tmr2us(ulong t); void microdelay(int us); +/* ds port specific */ void dispfont(void); long ldiv(long num, long denom); diff --git a/io.h b/io.h index 8945f73..89afd74 100644 --- a/io.h +++ b/io.h @@ -627,10 +627,6 @@ enum Ipcdataout = 0xF00, Ipcgenirq = 1<<13, Ipcirqena = 1<<14, - - /* intr fom arm7 wifi */ - I7WFrxdone = 1<<8, - I7WFtxdone, }; /* @@ -685,3 +681,5 @@ struct Ioifc { int (* clrstat)(void); int (* deinit)(void); }; + +void addioifc(Ioifc *io); diff --git a/root/appl/nds/guide b/root/appl/nds/guide new file mode 100644 index 0000000..f6b79cc --- /dev/null +++ b/root/appl/nds/guide @@ -0,0 +1,31 @@ + +# usage +win sh +limbo morse.b +kill Morse | sh +read 16000 < /dev/audio | xd -u + +man -f man/1/morse + +echo -n morse | morse -e +echo -n '-- --- .-. ... . ' | morse -d + +echo -n '-- --- .-. ... . ' | morse -aec > morse.raw +morse -ad < morse.raw + +echo -n morse | morse -e | morse -aec | morse -ad +echo -n morse | morse -e | morse -aec | morse -ad | morse -d + +# random tests +man cons pointer | markov | fmt | morse -e +for i in 0 1 2 3 4 5 6 7 8 9{ + m=`{read $i < /dev/random | xd -u -c | sed 's/[0-9a-f][0-9a-f]//g'} + echo $m "{echo $m | morse -e} + echo -n $m | morse -e | morse -aec > /dev/audio +} +for i in 0 1 2 3 4 5 6 7 8 9{ + m=`{read 32 < /dev/random | md5sum | tr a-z A-Z} + echo $m + echo -n $m | morse -e | morse -ae | morse -ad | morse -d + echo +} diff --git a/root/appl/nds/mkfile b/root/appl/nds/mkfile index 99598de..70b8c04 100644 --- a/root/appl/nds/mkfile +++ b/root/appl/nds/mkfile @@ -1,10 +1,12 @@ -<../../../mkconfig +<../../../../mkconfig +#<../../../../../mkconfig TARG=\ touchprint.dis\ memfiddle.dis\ rawimage.dis\ imagerle.dis\ + morse.dis\ MODULES=\ diff --git a/root/appl/nds/morse.b b/root/appl/nds/morse.b index 0a36f7d..683d7f6 100644 --- a/root/appl/nds/morse.b +++ b/root/appl/nds/morse.b @@ -1,6 +1,8 @@ # -# based on contrib/zswanch/morse.c, by 20h -# modified limbo version, by saoret.one +# morse - morse code encoder/decoder +# see the accompanying morse(1) man page +# written by Salva Peiro +# implement Morse; @@ -11,175 +13,196 @@ include "arg.m"; arg: Arg; include "string.m"; str: String; -include "sh.m"; +include "math.m"; + math: Math; Morse: module { - DITLEN: con 1; - DAHLEN: con 3; - WRDLEN: con 50; - CSILLEN: con 3; - WSILLEN: con 7; - - DEC, AUD, INP: con 1<Context, argv: list of string); + + morenct: fn(in,out: ref Sys->FD); # text to morse + mordect: fn(in,out: ref Sys->FD); # morse to text + morenca: fn(in,out: ref Sys->FD); # morse to audio + mordeca: fn(in,out: ref Sys->FD); # audio to morse + morkbdi: fn(in,out: ref Sys->FD); # keyboard to morse +}; + +amorse := array[] of { + ("A", ".-"), ("B", "-..."), ("C", "-.-."), ("D", "-.."), + ("E", "."), ("F", "..-."), ("G", "--."), ("H", "...."), + ("I", ".."), ("J", ".---"), ("K", "-.-"), ("L", ".-.."), + ("M", "--"), ("N", "-."), ("O", "---"), ("P", ".--."), + ("Q", "--.-"), ("R", ".-."), ("S", "..."), ("T", "-"), + ("U", "..-"), ("V", "...-"), ("W", ".--"), ("X", "-..-"), + ("Y", "-.--"), ("Z", "--.."), - mksample: fn(s: self ref Sample, morse: string); - addsound: fn(s: self ref Sample, units,timeunit: int); - addsilence: fn(s: self ref Sample, units,timeunit: int); + ("1", ".----"), ("2", "..---"), ("3", "...--"), ("4", "....-"), + ("5", "....."), ("6", "-...."), ("7", "--..."), ("8", "---.."), + ("9", "----."), ("0", "-----"), + + ("Á", ".--.-"), ("Ä", ".-.-"), ("É", "..-.."), ("Ñ", "--.--"), + ("Ö", "---."), ("Ü", "..--"), + (".", ".-.-.-"), (",", "--..--"), ("?", "..--.."), ("'", ".----."), + ("!", "-.-.--"), ("/", "-..-."), ("-", "-....-"), ("(", "-.--."), + (")", "-.--.-"), ("&", "-.-.-"), (":", "---..."), (";", "-.-.-."), + ("=", "-...-"), ("_", "..--.-"), + ("\"", ".-..-."),("@", ".--.-."), ("+", ".-.-."), ("$", "...-..-"), + ("*", ".-..."), ("#", "-...-.-"), + ("\n", "...-.-"), (" ", " "), }; - init: fn(ctxt: ref Draw->Context, argv: list of string); - morenc: fn(in, out: ref Sys->FD); - mordec: fn(in, out: ref Sys->FD); - morplay:fn(in: ref Sys->FD); +TONELEN: con 16; # bytes +tone := array [TONELEN] of { + byte 16rA7, byte 16r81, byte 16rA7, byte 16r00, + byte 16r59, byte 16r7F, byte 16r59, byte 16r00, +}; + +space := array [TONELEN] of { + byte 16r00, byte 16r00, byte 16r00, byte 16r00, + byte 16r00, byte 16r00, byte 16r00, byte 16r00, }; -# TODO -# while (not bored){ -# revise it; -# test it; -# use it; -# document it; -# } - -all := array[] of { - "A", ".-", "B", "-...", "C", "-.-.", "D", "-..", - "E", ".", "F", "..-.", "G", "--.", "H", "....", - "I", "..", "J", ".---", "K", "-.-", "L", ".-..", - "M", "--", "N", "-.", "O", "---", "P", ".--.", - "Q", "--.-", "R", ".-.", "S", "...", "T", "-", - "U", "..-", "V", "...-", "W", ".--", "X", "-..-", - "Y", "-.--", "Z", "--..", - "1", ".----", "2", "..---", "3", "...--", "4", "....-", - "5", ".....", "6", "-....", "7", "--...", "8", "---..", - "9", "----.", "0", "-----", - "Á", ".--.-", "Ä", ".-.-", "É", "..-..", "Ñ", "--.--", - "Ö", "---.", "Ü", "..--", - ".", ".-.-.-", ",", "--..--", "?", "..--..", "'", ".----.", - "!", "-.-.--", "/", "-..-.", "-", "-....-", "(", "-.--.", - ")", "-.--.-", "&", "-.-.-", ":", "---...", ";", "-.-.-.", - "=", "-...-", "/", "-..-.", "-", "-....-", "_", "..--.-", - "\"", ".-..-.","@", ".--.-.", "+", ".-.-.", "$", "...-..-", - "*", ".-...", "#", "-...-.-", - "SOS", "...---...", - "\n", "...-.-"," ", " ", - nil, nil }; - -Sample.mksample(s: self ref Sample, morse: string) +# http://www.comportco.com/~w5alt/cw/cwindex.php?pg=5 +Wave.init(A, W, P: int) +{ + x := Q20(2.0 * math->Pi * real W * (real 1.0 / real ARATE)); + for (i := 0; i < TONELEN; i++) + { + tone[i] = byte (Q20(A) * Q20(math->sin(real (x*Q20(i) + Q20(P))))); + space[i] = byte 16r00; + + # dprints the tone to fix it at compile time + dprint(sys->sprint("byte 16r%.2X, ", int tone[i])); + if(i % 4 == 3) + dprint("\n"); + } +} + +Wave.tone(s: self ref Wave, n,tdit: int) +{ + for (i:=0; i 100){ - # if the characters are to be sent slowly (less than 12wpm) - # compress the elements, and stretch the gap between the characters - - # to keep the wpm the same - comp = (real timeunit / real 100) - 1.0; - timeunit = 100; - }else{ - comp = 0.0; + comp := Q20(0); # compression factor + if(wpm <= 12){ + # for low wpm compress the elements, + # stretching the silences to maintain wpm + comp = (Q20(tdit) / Q20(100)) - Q20(1); + tdit = 100; } - slen = 0; + n = 0; extra = 0; - for (i = 0; i < len morse; i++){ - c = morse[i]; + for (i := 0; i < len morse; i++){ + c := morse[i]; if (c == '.'){ extra += DITLEN + DITLEN; - slen += DITLEN + DITLEN; + n += DITLEN + DITLEN; }else if (c == '-'){ extra += DAHLEN + DITLEN; - slen += DAHLEN + DITLEN; + n += DAHLEN + DITLEN; }else if (c == ' '){ - extra += CSILLEN - DITLEN; - slen += CSILLEN - DITLEN + int (real extra * comp); + extra += SPCLEN - DITLEN; + n += SPCLEN - DITLEN + int (Q20(extra) * comp); }else if (c == '/'){ - extra += WSILLEN - DITLEN; - slen += WSILLEN - DITLEN + int (real extra * comp); + extra += WSPCLEN - DITLEN; + n += WSPCLEN - DITLEN + int (Q20(extra) * comp); } } s.n = 0; - s.d = array[slen*8*timeunit] of { * => byte 0}; + s.d = array[n*tdit*TONELEN] of byte; extra = 0; for (i = 0; i < len morse; i++){ - c = morse[i]; + c := morse[i]; if (c == '.'){ extra += DITLEN + DITLEN; - s.addsound(DITLEN, timeunit); - s.addsilence(DITLEN, timeunit); + s.tone(DITLEN, tdit); + s.space(DITLEN, tdit); }else if (c == '-'){ extra += DAHLEN + DITLEN; - s.addsound(DAHLEN, timeunit); - s.addsilence(DITLEN, timeunit); + s.tone(DAHLEN, tdit); + s.space(DITLEN, tdit); }else if (c == ' '){ - extra += CSILLEN - DITLEN; - s.addsilence(CSILLEN - DITLEN + int (real extra * comp), timeunit); + extra += SPCLEN - DITLEN; + s.space(SPCLEN - DITLEN + int (Q20(extra) * comp), tdit); extra = 0; }else if (c == '/'){ - extra += WSILLEN - DITLEN; - s.addsilence(WSILLEN - DITLEN + int (real extra * comp), timeunit); + extra += WSPCLEN - DITLEN; + s.space(WSPCLEN - DITLEN + int (Q20(extra) * comp), tdit); extra = 0; } } } -Sample.addsound(s: self ref Sample, units,timeunit: int) -{ - for (i:=0; iFD) { - cfd := sys->open("/dev/audioctl", Sys->ORDWR); - sys->write(cfd, array of byte ctl, len ctl); -} - -morenc(in, out: ref sys->FD) -{ - c := array[1] of { * => byte 0}; + c := array[1] of byte; i := 0; - while(sys->readn(in, c, 1) > 0) { + while(sys->readn(in, c, 1) > 0){ C := str->toupper(string c); - for(i = 0; all[i] != nil; i += 2) { - if(C == all[i]) { - sys->fprint(out, "%s ", all[i + 1]); + for(i = 0; i < len amorse; i++){ + (t, m) := amorse[i]; + if(C == t){ + sys->fprint(out, "%s ", m); break; } } @@ -187,19 +210,20 @@ morenc(in, out: ref sys->FD) sys->fprint(out, "\n"); } -mordec(in, out: ref sys->FD) +# decode morse to text +mordect(in,out: ref sys->FD) { - cc := array[16] of { * => byte 0}; - c := array[1] of { * => byte 0}; + cc := array[16] of byte; + c := array[1] of byte; b := 0; i := 0; - while(sys->readn(in, c, 1) > 0) { + while(sys->readn(in, c, 1) > 0){ if((c[0] == byte '.' || c[0] == byte '-') && i < len cc) cc[i++] = c[0]; - if(c[0] == byte ' ') { - if(i == 0) { + if(c[0] == byte ' '){ + if(i == 0){ if(b >= 1) { sys->fprint(out, " "); b = 0; @@ -208,9 +232,10 @@ mordec(in, out: ref sys->FD) continue; } CC := string cc[0:i]; - for(i = 1; all[i] != nil; i += 2) { - if(CC == all[i]) { - sys->fprint(out, "%s", all[i - 1]); + for(i = 0; i < len amorse; i++){ + (t, m) := amorse[i]; + if(CC == m){ + sys->fprint(out, "%s", t); break; } } @@ -220,47 +245,185 @@ mordec(in, out: ref sys->FD) } } -morplay(in: ref sys->FD) +rf(file: string): string { + fd := sys->open(file, Sys->OREAD); buf := array[128] of byte; - sample := ref Sample; + nr := sys->read(fd, buf, len buf); + if(nr > 0) + return string buf[0:nr]; + return nil; +} + +wf(file, s: string): int +{ + fd := sys->open(file, Sys->ORDWR); + return sys->write(fd, array of byte s, len s); +} + +morenca(in,out: ref sys->FD) +{ + w := ref Wave; + c := array[1] of byte; + + while(sys->readn(in, c, len c) > 0){ + w.mk(string c); + if (sys->write(out, w.d, len w.d) < 0) + warn(sys->sprint("morenca: %r\n")); + } +} + +# uses Goertzel algorithm for signal detection, +# variations in W can help to tune/detect the right freq. +# see http://www.embedded.com/story/OEG20020819S0057 + +mordeca(in,out: ref sys->FD) +{ + sample:= array[N] of byte; + st := ref State(0, 0, ""); + + k, w: Q28; + c, q0, q1, q2: Q28; + + # check that N is a good choice + dprint(sys->sprint("demorse: W %% (ARATE / N) == %d\n", W % (ARATE / N))); + + k = Q28((1 + 2 * N * W / ARATE) / 2); # W is target signal's freq + w = Q28(2.0 * math->Pi) / Q28(N) * k; # freq + c = Q28(2.0 * math->cos(real w)); # coefficient + + for(;;){ + if(sys->read(in, sample, len sample) == 0) + break; + + q1 = Q28(0); + q2 = Q28(0); + for(i:=0; i < len sample; i++){ + q0 = c * q1 - q2 + Q28(sample[i]); + q2 = q1; + q1 = q0; + } + + m2 := q1*q1 + q2*q2 - q1*q2*c; + slice(int m2, st); + } + +# mc := ""; for(i:=0; i < len st.m; i++) if(st.m[i] != '_') mc[len mc] = st.m[i]; + sys->fprint(out, "%s\n", st.m); +} + +State: adt +{ + t: int; # tones + s: int; # silences + m: string; +}; + +# break input into slices: tone/silence +slice(m: int, s: ref State) +{ + tdit: int = (60*1000)/(wpm*WORDLEN); + ditlen: int = DITLEN*tdit*TONELEN/N - 1; - audioctl("rate 8000\n bits 8\n chans 1\n"); - - afd := sys->open("/dev/audio", Sys->ORDWR); - while(sys->read(in, buf, len buf) > 0){ - sys->print("buf: %s\n", string buf); - sample.mksample(string buf); - if (sys->write(afd, sample.d, len sample.d) < 0) - sys->print("bad write\n"); + istone := (m < -T || +T < m); + s.t += istone; + s.s += !istone; + + if(s.t > ditlen){ + s.t = 0; + s.s = 0; + s.m += "."; + lenm := len s.m; + if(lenm >= 3 && s.m[lenm-3:lenm] == "..."){ + s.m = s.m[0:lenm-3] + "-"; + } + } + + if(s.s > ditlen){ + s.t = 0; + s.s = 0; + s.m += "_"; + lenm := len s.m; + if(lenm >= 3 && s.m[lenm-3:lenm] == "___"){ + s.m = s.m[0:lenm-3] + " "; + } } + + dprint(sys->sprint("mo %d %d %d ", m, s.t, s.s)); + dprint(sys->sprint("m %s\n", s.m)); } -morinput(in: ref sys->FD) +# keyboard press/release timings (ms) +KDITLEN: con 300; # short press +KDAHLEN: con 500; # long press + +morkbdi(in,out: ref sys->FD) { - t, d: int; - c := array[1] of { * => byte 0}; + t, d, k: int; + c := array[1] of byte; + wf("/dev/consctl", "rawon"); while(sys->readn(in, c, 1) > 0) { d = sys->millisec() - t; - if (d < 40) - c[0] = byte '-'; - else if (d < 160) - c[0] = byte '.'; + if(d <= KDITLEN) + k = '.'; + else if(d <= KDAHLEN) + k = '-'; else - c[0] = byte ' '; + k = ' '; - sys->print("%c", int c[0]); + dprint(sys->sprint("k %c %d.%d\n", k, d / 1000, d % 1000)); + if(k != ' ') + sys->fprint(out, "%c", k); t = sys->millisec(); } - sys->print("\n"); + sys->fprint(out, "\n"); +} + +# audio settings +ABITS: con 8; +AENC: con "pcm"; +ACHANS: con 1; +ARATE: con 8000; + +# test/set the audio settings +audioctl(set: int) +{ + audioctl := array [] of { + "bits " + string ABITS, + "enc " + string AENC, + "chans "+ string ACHANS, + "rate " + string ARATE, + }; + + if(set){ + for(i:=0; i < len audioctl; i++) + if(wf("/dev/audioctl", audioctl[i]) != len audioctl[i]) + warn("audioctl: bad write\n"); + }else{ + # TODO: read on audioctl sigsegv/linux + s := rf("/dev/audioctl"); + for(i:=0; i < len audioctl; i++) + warn("audioctl: bad read\n"); + } +} + +dflag: int; +dprint(s: string) +{ + if(dflag) + sys->fprint(sys->fildes(2), "%s", s); } -usage() +warn(s: string) { - sys->print("usage: morse [-d] [-a]\n"); - exit; + sys->fprint(sys->fildes(2), "%s", s); +} + +usage(diag: string) +{ + sys->print("usage: morse [-Dic] [-atde] [-w wpm] [-A amp] [-W freq]\n%s", diag); } init(nil: ref Draw->Context, args: list of string) @@ -268,29 +431,54 @@ init(nil: ref Draw->Context, args: list of string) sys = load Sys Sys->PATH; arg = load Arg Arg->PATH; str = load String String->PATH; + math = load Math Math->PATH; + + stdin := sys->fildes(0); + stdout := sys->fildes(1); + + wpm = DFLTWPM; + (A, W, P) = (DFLTAMP, DFLTFREQ, DFLTPHASE); + (N, T) = (DFLTBLK, DFLTTHR); mode := 0; arg->init(args); while((c := arg->opt()) != 0) case c { 'a' => mode |= AUD; - 'd' => mode |= DEC; - 'i' => mode |= INP; - * => usage(); + 't' => mode &= ~AUD; + 'd' => mode &= ~ENC; + 'e' => mode |= ENC; + + 'k' => morkbdi(stdin, stdout); + + 'w' => (wpm, nil) = str->toint(arg->arg(), 10); + 'A' => (A, nil) = str->toint(arg->arg(), 10); + 'W' => (W, nil) = str->toint(arg->arg(), 10); + 'P' => (P, nil) = str->toint(arg->arg(), 10); + + 'N' => (N, nil) = str->toint(arg->arg(), 10); + 'T' => (T, nil) = str->toint(arg->arg(), 10); + + 'D' => dflag++; + 'c' => audioctl(1); + + * => usage(nil); exit; } args = arg->argv(); - stdin := sys->fildes(0); - stdout := sys->fildes(1); + Wave.init(A, W, P); - if (mode & INP) - morinput(stdin); - if (mode & AUD) - morplay(stdin); - if (mode & DEC) - mordec(stdin, stdout); - else - morenc(stdin, stdout); - - exit; + dprint(sys->sprint("mode %x\n", mode)); + if(mode & AUD){ + # audioctl(0); + if(mode & ENC) + morenca(stdin, stdout); + else + mordeca(stdin, stdout); + }else{ + if(mode & ENC) + morenct(stdin, stdout); + else + mordect(stdin, stdout); + } } diff --git a/root/man/1/morse b/root/man/1/morse new file mode 100644 index 0000000..7c26737 --- /dev/null +++ b/root/man/1/morse @@ -0,0 +1,148 @@ +.TH MORSE 1 + +.SH NAME +morse \- a Morse code encoder/decoder + +.SH SYNOPSIS +.B morse +[ +.B -dic +] [ +.B -at +] [ +.B -de +] [ +.B -w +.I wpm +] [ +.B -A +.I ampl +] [ +.B -W +.I freq +] +. + +.SH DESCRIPTION +.B Morse +is a program that speaks (encodes) and understands (decodes) Morse code. +Morse data can be either in textual format (Morse elements: [.- ]) or +in audio format (PCM samples). + +.PP +Morse expects data to come from stdin, processes it, and and sends the result to stdout. + +This allows to decouple the various operation modes, and allow +multiple variations (using pipes, see the examples below). +Moreover it allows to separe signal recording +from audio processing and decoding, +which eases testing and implementation. + +.SS Options +.TP +.B -d +Print debugging messages. +.TP +.B -i +Uses the Enter key, to input on/off morse symbols. +.TP +.B -c +Either checks or sets the +.IR audio (3) +settings (encoding, speed, bits, channels) + +.TP +.B -[at] +Select the data format which can be either: audio (a) or text (t). +.TP +.B -[de] +Either perform Morse decoding (d) or encoding (e). + +.TP +.B -w wpm +Set the morse code speed to +.I wpm +words per minute. +.TP +.BI -A " ampl " +Set the +.I amplitude +of the sinusoidal wave used in the morse audio samples. +.TP +.BI -W " freq " +Set the +.I frequency +of the sinusoidal wave used in the morse audio samples. + +.SH EXAMPLE +Encode text into morse code and viceversa: +.EX + echo -n morse | morse -e + echo -n '-- --- .-. ... . ' | morse -d +.EE +And to encode into audible morse code and viceversa: +.EX + echo -n '-- --- .-. ... . ' | morse -aec > morse.raw + morse -ad < morse.raw +.EE + +Moreover is possible to close the encode/decode loop +.EX + echo -n morse | morse -e | morse -aec | morse -ad + echo -n morse | morse -e | morse -aec | morse -ad | morse -d + ... +.EE + +Where the last pipe (|) could be replaced by any +medium capable of transmitting the data; +either in electronic, audible or RF waves. + +.PP + +This allows to implement a kind of remote control +to access devices by sending/receiving morse code. + +Some interesting articles out there provide some +usage ideas/examples for +.BR Morse : + +.IP +.B - http://www.learnmorsecode.com/ +.IP +.B - http://en.wikipedia.org/wiki/Text_messaging +.IP +.B - http://www.staton.us/electronics/cpc/cpc.html +.IP +.B - http://5b4az.chronos.org.uk/pages/morse.html + +.SH STATUS + +.B Morse +is a work in progress, +an experiment performed to learn (by doing something useful/interesting) +about the fields of Morse, audio & signal processing. + +.PP +Ideas, suggestions and improvements are welcome. + +.SH REFERENCES + +.IP ``The Radio Amateur's Handbook (ARRL)'', +.B http://www.arrl.org/catalog/?words=arrl+handbook +, for details about radio and Morse code, eg. the alphabet, encoding and decoding. + +.IP ``The Scientist and Engineer's Guide to Digital Signal Processing'', +.B http://www.dspguide.com/pdfbook.htm +and +.IP ``The Spectral Audio Signal Processing book'' +.B http://www.dsprelated.com/dspbooks/sasp +, for details related with Goertzel tone detection algorithm and digital audio. + + +.SH SOURCE +.B /appl/cmd/nds/morse.b +.br + +.SH SEE ALSO +.IR audio (6), +.IR audio (3) diff --git a/root/man/1/morse.html b/root/man/1/morse.html new file mode 100644 index 0000000..40a9241 --- /dev/null +++ b/root/man/1/morse.html @@ -0,0 +1,206 @@ + +Inferno's MORSE(1 +) + + +[manual index][section index]

+ +

NAME +

+
+morse - a Morse code encoder/decoder + +

SYNOPSIS +

+
+morse + +[ +-dic + +] [ +-at + +] [ +-de + +] [ +-w + +wpm + +] [ +-A + +ampl + +] [ +-W + +freq + +] + +

DESCRIPTION +

+
+Morse + +is a program that speaks (encodes) and understands (decodes) Morse code. +Morse data can be either in textual format (Morse elements: [.- ]) or +in audio format (PCM samples). + +

Morse expects data to come from stdin, processes it, and and sends the result to stdout. + +This allows to decouple the various operation modes, and allow +multiple variations (using pipes, see the examples below). +Moreover it allows to separe signal recording +from audio processing and decoding, +which eases testing and implementation. + +

Options + +
+
+
-d + +
Print debugging messages. +
-i + +
Uses the Enter key, to input on/off morse symbols. +
-c + +
Either checks or sets the +audio(3) + +settings (encoding, speed, bits, channels) + +
-[at] + +
Select the data format which can be either: audio (a) or text (t). +
-[de] + +
Either perform Morse decoding (d) or encoding (e). + +
-w wpm + +
Set the morse code speed to +wpm + +words per minute. +
-A ampl +
Set the +amplitude + +of the sinusoidal wave used in the morse audio samples. +
-W freq +
Set the +frequency + +of the sinusoidal wave used in the morse audio samples. + +
+
+

EXAMPLE +

+
+Encode text into morse code and viceversa: +
+	echo -n morse | morse -e
+	echo -n '-- --- .-. ... . ' | morse -d
+
+And to encode into audible morse code and viceversa: +
+	echo -n '-- --- .-. ... . ' | morse -aec > morse.raw
+	morse -ad < morse.raw
+
+ +Moreover is possible to close the encode/decode loop +
+	echo -n morse | morse -e | morse -aec | morse -ad
+	echo -n morse | morse -e | morse -aec | morse -ad | morse -d
+	...
+
+ +Where the last pipe (|) could be replaced by any +medium capable of transmitting the data; +either in electronic, audible or RF waves. + +

+This allows to implement a kind of remote control +to access devices by sending/receiving morse code. + +Some interesting articles out there provide some +usage ideas/examples for +Morse: + + +

+

+

- http://www.learnmorsecode.com/ + +

+

- http://en.wikipedia.org/wiki/Text_messaging + +

+

- http://www.staton.us/electronics/cpc/cpc.html + +

+

- http://5b4az.chronos.org.uk/pages/morse.html + + +
+

STATUS +

+
+ +Morse + +is a work in progress, +an experiment performed to learn (by doing something useful/interesting) +about the fields of Morse, audio & signal processing. + +

Ideas, suggestions and improvements are welcome. + +

REFERENCES +

+
+ +
+
``The Radio Amateur's Handbook (ARRL)'', + +
http://www.arrl.org/catalog/?words=arrl+handbook + +, for details about radio and Morse code, eg. the alphabet, encoding and decoding. + +

``The Scientist and Engineer's Guide to Digital Signal Processing'', + +
http://www.dspguide.com/pdfbook.htm + +and +

``The Spectral Audio Signal Processing book'' + +
http://www.dsprelated.com/dspbooks/sasp + +, for details related with Goertzel tone detection algorithm and digital audio. + + +
+

SOURCE +

+
+/appl/cmd/nds/morse.b + +
+ +

SEE ALSO +

+
+audio(6), +audio(3) + +
+

+ +
MORSE(1 +)Rev:  Sun Mar 15 11:06:21 GMT 2009
diff --git a/root/man/mkfile b/root/man/mkfile new file mode 100644 index 0000000..ea4e608 --- /dev/null +++ b/root/man/mkfile @@ -0,0 +1,6 @@ +<../mkconfig + +MAN=\ + 1/morse\ + + $stem.html + +all:QV: + +clean:QV: + +install:V: $MANFILES + +nuke:V: + rm -f $MANFILES diff --git a/sds b/sds index 3e5d065..0b8bd30 100644 --- a/sds +++ b/sds @@ -108,6 +108,7 @@ code init dsinit +# tstdraw root /chan / diff --git a/trap.c b/trap.c index a19e74f..64f2918 100644 --- a/trap.c +++ b/trap.c @@ -80,7 +80,7 @@ intrenable(int sort, int v, void (*f)(Ureg*, void*), void* a, char *tbdf) { int x; - USED(tbdf); + USED(sort, tbdf); if(v < 0 || v > MaxIRQbit) panic("intrenable: irq source %d out of range\n", v); Irq[v].r = f;