Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
nogy committed Aug 31, 2010
0 parents commit 9ff225c
Show file tree
Hide file tree
Showing 11 changed files with 396 additions and 0 deletions.
18 changes: 18 additions & 0 deletions AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nogy.afu.soundmodem"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".soundmodem"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>


</manifest>
19 changes: 19 additions & 0 deletions README
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Welcome to jsoundmodem,

this project was set up to enable APRSDroid to communicate via transceivers.
Therefore it is still very limited right now.

Working features:
- Afsk modulator
- APRSFrame packet builder
- generic Message class to store not byte-aligned messages and their
length in bits. (Being unaligned is a painful property of messages
after being bit stuffed

Next to come:
- I'm thinking of an Afsk demodulator
- Extending the APRSFrame packet builder to a generic APRS packet
handler

Bastian Müller
08/31/2010
Binary file added res/drawable-hdpi/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-ldpi/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/drawable-mdpi/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions res/layout/main.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>


<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TX" android:id="@+id/B_TX" android:onClick="do_TX"></Button>
</LinearLayout>
5 changes: 5 additions & 0 deletions res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, soundmodem!</string>
<string name="app_name">soundmodem</string>
</resources>
203 changes: 203 additions & 0 deletions src/com/nogy/afu/soundmodem/APRSFrame.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
/*
* APRS Frame generator
*
* this class generates an AX.25 compliant UI Frame incl. bit stuffing.
*
* 08/29/2010
* Bastian Müller
*
*/
package com.nogy.afu.soundmodem;

import android.test.IsolatedContext;

public class APRSFrame {
private String srca; // Source Address
private String desta; // Destination Address
private String digia; // Digipeater Addresses
private byte cf; // controll field
private byte protoId;
private String data;
private byte flag;
private int framelength;

public APRSFrame (String source, String destination, String digipeaters, String data, int framelength)
{
this.cf = 0x03;
this.protoId = -16; // = 0xf0
this.flag = 0x7e;
this.srca = source;
this.desta = destination;
this.digia = digipeaters;
this.data = data;
this.framelength = framelength;
}

public static byte[] crc16(byte[] d)
{
byte[] out = new byte[2];
int crc = 0xFFFF;
int crcpoly = 0x8408;
int i,k=0;
for (i=0; i<d.length-2; i++)
for (k=0; k<8; k++)
{
if ((crc & 1) != ((d[i] & (1 << k))>>k))
crc = ((crc >> 1) ^ crcpoly) & 0xFFFF;
else
crc >>= 1;
}
crc ^= 0xFFFF;
out[1] = (byte)(((crc & 0xff00) >> 8)-255-1); // high byte
out[0] = (byte)((crc & 0xff)-255-1); // low byte
return out;
}

public static Message bitStuffAndFrame(byte[] d, int framelength)
{
byte[] out = new byte[d.length+framelength+(int)Math.ceil(d.length/5)+1];
int i,k=0;
int ones;//,bits,bytes;
// bits =0;
// bytes =0;
ones = 0;
int temp = 0;
for (i=0; i<out.length; i++)
out[i] = 0;
for (i=0; i<framelength; i++)
out[i] = 0x7e;
i=0;
k=framelength*8;
while (i<d.length*8)
{
if ((d[i/8] & (1<<(i%8))) > 0) // current bit == 1
{

out[k/8] |= ((1 << (k%8))>127)? (byte)((1 << (k%8))-256): (byte)(1 << (k%8)); // insert
if (ones++ == 4) // going to stuff a 0
{
k++;
ones = 0;
}
}
else
{
ones = 0;
}
i++;
k++;
}
i=0;
while ((i)<8)
{
if ((0x7e & (1<<(i%8))) > 0) // current bit == 1
{
out[k/8] |= ((1 << (k%8))>127)? (byte)((1 << (k%8))-256): (byte)(1 << (k%8)); // insert
}
k++;
i++;
}
Message m = new Message();
m.numberOfBits = k+1;
m.data = out;
return m;
}

private byte[] parseCall(String call, boolean isDest)
{
byte[] out = new byte[7]; // Always 7 Byte long
String[] mycall;
mycall = call.split("-");
char[] c = mycall[0].toUpperCase().toCharArray();

int i=0;

for (i=0; i<6; i++)
out[i] = 0x40;

i=0;

while (i<c.length)
{
out[i] = (byte)(((int)(c[i])) << 1);
i++;
}
while (i<6)
{
out[i++] = 0x40; // Fill with Spaces
}
if (mycall.length>1)
{
switch (Integer.parseInt(mycall[1]))
{
case 0: out[6] = 0x60; break;
case 1: out[6] = 0x62; break;
case 2: out[6] = 0x64; break;
case 3: out[6] = 0x66; break;
case 4: out[6] = 0x68; break;
case 5: out[6] = 0x6A; break;
case 6: out[6] = 0x6C; break;
case 7: out[6] = 0x6E; break;
case 8: out[6] = 0x70; break;
case 9: out[6] = 0x72; break;
case 10: out[6] = 0x74; break;
case 11: out[6] = 0x76; break;
case 12: out[6] = 0x78; break;
case 13: out[6] = 0x7A; break;
case 14: out[6] = 0x7C; break;
default: out[6] = 0x60; break;
}
}
else
out[6] = 0x60; // SSID 0 as default;
if (isDest) // set ssid-msb to 1
{
out[6] |= 0x80;
}
return out;
}

public Message getMessage()
{
String[] digis = this.digia.split(",");
byte[] out = new byte[14+digis.length*7+2+this.data.length()+2];
byte[] temp;
int k,i=0;
temp = parseCall(this.desta, true);
while(i<7) // Fill in source
{
out[i] = temp[i];
i++;
}
temp = parseCall(this.srca, false);
while(i<14) // Fill in dest
{
out[i] = temp[i-7];
i++;
}
for (k=0; k<digis.length; k++) // Parse an fill in Digis
{
temp = parseCall(digis[k],false);
while(i<21+k*7)
{
out[i] = temp[i-14];
i++;
}
}
out[i-1] |= 0x01;
out[i++] = this.cf;
out[i++] = this.protoId;
k=0;
while (k<this.data.length())
{
out[i++] = (byte)(((int)(data.charAt(k++))) -256);
}
temp = crc16(out);
out[i++] = temp[0];
out[i] = temp[1];
return bitStuffAndFrame(out, this.framelength);
}



}
90 changes: 90 additions & 0 deletions src/com/nogy/afu/soundmodem/Afsk.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* AFSK modulator
*
* This class helps sending out AFSK modulated data packets for e.g. hamradio use
*
* 08/27/2010
* Bastian Müller
*
*/

package com.nogy.afu.soundmodem;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;

public class Afsk {
public static int f_low = 1200;
public static int f_high = 2200;
public static int bps = 1200;
public static int samplerate = 12000;
public static int pcmBits = 16;

public short[] pcmData;

private AudioTrack a;

private float volume;

public Afsk()
{
volume = AudioTrack.getMaxVolume()/2;
}

public void setVolume(float vol)
{
this.volume = vol;
}

public void sendMessage(Message m)
{
int i,k=0;
int t=0;
int datapoint=0;
double cospos=0;
int lasttone=f_low;
pcmData = new short[(m.numberOfBits*samplerate)/bps];
for (i=0; i<m.numberOfBits; i++)
{


t=0;
if ((m.data[i/8] & (1<<(i%8)))==0) // bit to transmit is 0
{
lasttone = (lasttone==f_low)?f_high:f_low;
}
while(t++<samplerate/bps)
{
pcmData[datapoint++]=(short) Math.round(Math.cos(cospos)*((1 << (pcmBits-1))-1));

cospos += 2*Math.PI*lasttone/samplerate;
if (cospos > 2*Math.PI)
cospos -= 2*Math.PI;
}

}
sendPCM();

}

private void sendPCM()
{
a = new AudioTrack(
AudioManager.STREAM_MUSIC,
samplerate,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT,
pcmData.length*2,
AudioTrack.MODE_STATIC
);
a.setPlaybackRate(samplerate);
a.write(pcmData, 0, pcmData.length);
a.setStereoVolume(this.volume, this.volume);
a.play();
//a.g

}


}
15 changes: 15 additions & 0 deletions src/com/nogy/afu/soundmodem/Message.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Simple struct type of class 'cause I needed it
* Contains a bit stuffed AX.25 UI Frame
*
* 08/29/2010
* Bastian Müller
*
*/

package com.nogy.afu.soundmodem;

public class Message {
public int numberOfBits;
public byte[] data;
}
Loading

0 comments on commit 9ff225c

Please sign in to comment.