NThis hack should work with any software that supports OTRSP protocol. (or MKII protocol)

The hack is based on the following fact about DVR enabled Icom radios:

Although you could use a series of resistors and switching transistors, this solution is NOT cool!

A cooler solution is to use a digital pot such as the MCP4231 controlling it via a simple arduino like the nano with a USB serial port. This digital pot has 2x 0-10K resistors in linear 128 steps. When connected in series you can get 0-20K and the control is via SPI

(mode 0 and mode 3 supported)

Update:

My first attempt although worked fine, picked up RF and ended voice messages prematurely.

To counter act this, I added a small miniature relay on one of the outputs such that after the message is triggered the circuit is taken physically off.

The relay trigger was on pin A1. Updated schematic and code appear below

There is still problem though with RF feedback that makes this unusable on some bands. My next solution is to solder a DPDT relay to physically disconnect both mic pins after the relay has been triggered off!

Here is the schematic!

You can use any digital or analog pins but configure the correct one in the code

I am using A0 for VDD and A5 for CS (=Chip Select).

The code is simple:

Reset

Then switch on the pot (A0 HIGH) 5V to its DCC

Look out for the Serial commands from the software:

KP1, KP2, KP3 or KP4 or KA (Abort) as per OTSRSP

Put the resistance to the right level using SPI

Wait for 50ms for ICOM DVR to detect that

Put the resistance back to 20K using SPI

Listen to serial port

It uses MKII serial commands for now as win-test doesnt as yet support OTRSP voice keyer commands.

This code has been tested with an icom 756 pro III

#include <SPI.h>

/*

This software is written by Marios Nicolaou 5B4WN/G0WWW

Use this software at your own risk!

More details about this project http://www.5b4wn.com/main/a2138.html

Connections

arduino MOSI 11 to SDI 3

arduino CLK 13 to SCK 2

arduino CS 10 to CS 1

Resistance is 5 and 6 POT1

Resistrance is 10 and 9 POT0

putting them in series increases the range!

For Icom we need

Message 1 1.5K

Message 2 3K

Message 3 5.2K

Message 4 9.9K

For OTRSP see http://www.k1xm.org/OTRSP/OTRSP_Protocol.pdf

Commands supported

KP1 KP2 KP3 KP4

KA abort

Command terminated by \R

*/

int SSpin=19; //a5

int potPowerPin= 14; //a0

int relayOnPin=15; //a1

int pot0=0x10;

int pot1=0x0;

long timeSincePress;

String serialCommand;

int delayTime=60; //time for the resistance to be applied to the two pins of mic. Min is 50ms

void setup() {

//supported modes by MPC are mode 0 and mode 3

pinMode(SSpin, OUTPUT);

pinMode(potPowerPin, OUTPUT);

pinMode(relayOnPin, OUTPUT);

digitalWrite(relayOnPin, LOW);

digitalWrite(potPowerPin, HIGH); //powerUp Pot

SPI.setDataMode(0);

SPI.begin();

Serial.begin(9600); //OTRSP default 9600

Serial.println("5B4WN Icom voice keyer");

maxPot(); //go to 20K to avoid triggering the memory

timeSincePress=millis(); //initialise time

}

void loop() {

if (Serial.available()>0) {

byte buffer=Serial.read();

serialCommand +=(char) buffer;

if (serialCommand.length()>20) {

serialCommand=""; //avoid too long strings

}

if (buffer==0x0d) { //received a \r

if (serialCommand.startsWith("MP")) {

String memory=serialCommand.substring(2,3); //from 2 to 3!

Serial.println("Memory:"+memory);

if (memory=="1") {

digitalWrite(relayOnPin, HIGH);

writePot(pot0, 1500);

writePot(pot1, 1500);

delay(delayTime);

digitalWrite(relayOnPin, LOW);

maxPot();

timeSincePress=millis();

}

else if (memory=="2") {

digitalWrite(relayOnPin, HIGH);

writePot(pot0, 3000);

writePot(pot1, 3000);

delay(delayTime);

digitalWrite(relayOnPin, LOW);

maxPot();

timeSincePress=millis();

}

else if (memory=="3") {

digitalWrite(relayOnPin, HIGH);

writePot(pot0, 5200);

writePot(pot1, 5200);

delay(delayTime);

digitalWrite(relayOnPin, LOW);

maxPot();

timeSincePress=millis();

}

else if (memory=="4") {

digitalWrite(relayOnPin, HIGH);

writePot(pot0, 9900);

writePot(pot1, 9900);

delay(delayTime);

digitalWrite(relayOnPin, LOW);

maxPot();

timeSincePress=millis();

}

else {

}

serialCommand="";

}

else if (serialCommand.startsWith("MA")) {

//abort

if ((millis()-timeSincePress)<3000) { //if esc is pressed within 3 s (time for most messages) the resend control for message 1

digitalWrite(relayOnPin, HIGH);

writePot(pot0, 1500);

writePot(pot1, 1500);

delay(delayTime);

digitalWrite(relayOnPin, LOW);

maxPot();

timeSincePress=millis();

}

serialCommand="";

}

else if (serialCommand.startsWith("?NAME")) {

Serial.println ("5B4WN voice keyer");

}

else {

//some other command so ignore

serialCommand="";

}

}

} //serial.available

}

void writePot(int address, int valueOhms) {

int n=map(valueOhms, 0, 20000,0, 128);

digitalWrite(SSpin, LOW);

SPI.transfer(address);

SPI.transfer(n);

digitalWrite(SSpin, HIGH);

}

void maxPot() {

writePot(pot0, 20000); //go for 20K

writePot(pot1, 20000);

}

By: mnicolao added:14-03-2012 15:45 (modified: 29-03-2012 10:58)

VS1053b and arduino playing a file

Next step how to play a file from a FAT32 formatted SD card

eg 1.mp3

#include <SPI.h>

#include "VS1053.h"

#include <SD.h>

File myFile;

VS1053 player;

uint8_t mp3DataBuffer[ 32];

unsigned int modeValue;

const int chipSelect = 10;

void setup() {

Serial.begin(57600);

player.begin( 16, 17, 14, 15);

delay(100);

//do SD stuff

if (!SD.begin(chipSelect)) {

Serial.println("initialization failed!");

return;

}

Serial.println("initialization done.");

myFile=SD.open("1.mp3");

SPI.setClockDivider (SPI_CLOCK_DIV8);

player.Mp3SetVolume(0x30, 0x30);

player.Mp3SoftReset();

playFile(myFile);

}

void loop() {

}

void playFile(File myFile) {

Serial.print("opening file");

boolean moreData=true;

while (1) {

while (!digitalRead(player.dreqPin)){

if (moreData) {

if (!myFile.read(mp3DataBuffer,sizeof(mp3DataBuffer))) {

break;

}

moreData=false;

}

//check for commands

}

if (moreData) {

if (!myFile.read(mp3DataBuffer,sizeof(mp3DataBuffer))) {

break;

}

moreData=false;

}

player.streamBuffer(mp3DataBuffer);

moreData=true;

}

player.SPIWait();

player.sendEndFillByte();

myFile.close();

}

By: mnicolao added:04-03-2012 13:45

Playing hello using VS1053b and arduino

Having had a successful sign test the next step is to see if we can play the hello buffer

This has been a great challenge for me and I hope that I would be able to solve the interfacing problem of the arduino (IDE v1.0) with the VS1053b based shield such as this one

OK lets start by getting the sine wave test working:

For this to work here is the pseudocode:

Hardware Reset

Delay 100ms

Send Dummy char to initialize SPI eg 0xFF

pull xCS High (control)

pull xDCS high (data)

Release from reset

Delay 100ms

// go into test mode

pull xCS LOW (control)

Send SPI 0x02 WRITE

Send SPI 0x00 Register

Send SPI 0x08 MSB

Send SPI 0x20 LSB (Test mode)

check Complete transfer

Pull xCS High (Control)

Check DREQ

//start sine wave

pul xDCS low

Send 0x53 then 0xef then 0x6e 0x44 0x00 0x00 0x00 0x00

check complete transfer

put xDCS high

Delay

//stop sine test

pull xDCS LOW

Send 0x45, 0x78, 0x69, 0x74, 0x00, 0x00, 0x00, 0x00

Transfer complete

pull xDCS HIGH

etc

Here is the working example using my class

#include <SPI.h>

#include "VS1053.h"

VS1053 player;

unsigned int modeValue;

void setup() {

Serial.begin(9600);

player.begin( 16, 17, 14, 15);

delay(100);

}

void loop() {

player.hardReset();

player.testMode();

player.sineWaveStart();

delay(3000);

player.sineWaveStop();

delay(3000);

}

By: mnicolao added:03-03-2012 18:08 (modified: 03-03-2012 20:03)

Connecting a PICAXE OLED LCD to arduino

I recently bought this LCD from picaxe.com (AXE133Y). I was impressed by its quality and price and most importantly, I thought I could use it with my arduino projects by sacrificing only 1 pin.

Unfortunately this was not possible straight out of the box!

It seems that the 18M2 Picaxe chip prefers serial communication using inverted signals! The arduino uses normal signals so without modifying the firmware it is not possible for these devices to talk.

Modifying the code was straight forward but uploading it was simply a nightmare as I did not have the picaxe programming cable which looked exactly like my ftdi TTL-232 cable. There are 2 important differences:

1) The picaxe cable uses inverted signals whereas the FTDI cable uses non-inverted ones. The problem can be solved by using this program [use instructions here]

2) The wiring of the two cables is different

[ ] Tip

[ ] Ring

| |

| | Shield

[ ]

Picaxe Cable

FTDI cable

Tip

Shield

Shield

Ring

Ring

Tip

Finally here is the code I used for the firmware (all credit to www.picaxe.com

; AXE133 Serial LCD/OLED using PICAXE-18M2; Emulates basic serial operation of the popular AXE033 module
; CPS, May 2011
; This is an open source firmware
; This code has been modified by 5B4WN
; December 9, 2011
; All credits to www.picaxe.com

; Store the 16 character user defined messages in EEPROM data memory
; First two messages are optionally used as welcome message

; If using a display with 20 characters you will need to edit
; the start addresses to be multiples of 20 (currently at 16)
; and add 4 characters to each message.
; Please remember 4 line displays always use the strange 1-3-2-4 layout.

; NB keep character mode test as first item in this list to optimise speed
if b1 < 253 then
let pinsB = b1 ; output the data
pulsout enable,1 ; pulse the enable pin to send data.
goto main ; quickly loop back to top
else if b1 = 254 then
low rs ; change to command mode for next character
serin RX,baud,b1 ; wait for the command byte
let pinsB = b1 ; output the data
pulsout enable,1 ; pulse the enable pin to send data.
high rs ; back to character mode
goto main ; quickly loop back to top
else if b1 = 253 then
serin RX,baud,b1 ; wait for the next byte
gosub msg ; do the 16 character message
goto main ; back to top
else ; must be 255
serin RX,baud,b1 ; wait for the next byte
let pinsC = b1 & %00000111 | %10000000
; output the data on C.0 to C.1, keep RS high
goto main ; back to top
end if

K1XM has just published details of how to build an SO2R box using the arduino platform in NCJ.

Some of the features are:

switches headphones, microphone, CW keyer and PTT (from the computer or a footswitch)

uses relays for headphone and microphone switching

communicates through, and is powered by, a USB port

includes override switches for transmit and receive and LEDs to display status

incorporates aBLENDcontrol that blends left and right channels in stereo mode

provides four-bit outputs, with band information for each radio. The outputs are compatible with Array Solutions, Top-Ten, Unified Microsystems or similar band decoders.

includes a "latch" mode. If the computer transmits (i.e., sets PTT), the headphones will be connected in mono to the non-transmitting radio, reverting to normal operation when the radio stops transmitting.

can be set so it willnotgo into stereo - useful for people who have a hearing issue in one ear.

is compatible with N1MM Logger, WriteLog, Win-Test and similar logging programs

Icom rigs have their own unique way of providing information to external rigs based on the current band. This information is provided on a single pin on the ACC-2 socket by varying the voltage from 0-8V (see figure below).

Most peripheral equipment use the ubiquitous YAESU band data method as follows

This project uses an arduino to read the voltage from the ACC2 pin, determines the band and then converts it to a YAESU band data to use with the many peripherals that support the latter. Read more here.