# Sine wave amplitude to binary MATLAB lookup table

I'm trying to generate a 256 point 8-bit sine lookup table for digital synthesis. I wrote the below MATLAB code for generating the binary numbers from amplitude and copying into a data file. It works but the output is not symmetric as you can see. I don't know what I'm doing wrong. Can someone help me with this?

clear all; close all;
fs=40;
amp=1;
t=0:1/fs:2*pi;
sine_w=amp*sin(t);
figure();
plot(t,sine_w);
total_wordlength=8;
scaling=7;
sine_int=round(sine_w.*(2^scaling));
sine_binary=dec2bin(mod((sine_int),2^total_wordlength),total_wordlength);
yy=cellstr(sine_binary);
fid=fopen('sine_value.data','wt');
fprintf(fid, '%8s \n', yy{:});
display('text file for signal finished');

• In what way is it not symmetric? Commented Feb 13, 2022 at 9:38
• If you take the latter half of the list, invert it, fold it backwards it is the same sequence of numbers.
– Syed
Commented Feb 13, 2022 at 10:11
• You can always use an online tool for lookup table generation, for example my one: ppelikan.github.io/drlut
– ppel
Commented Feb 22, 2022 at 13:32

So I think you missed that dec2bin only works with unsigned numbers.

Here is my version which does a Two's complement conversion after generating a unsigned sine with offset

Note: Syntax like ++ only works with octave... if you use matlab, you need to do something like x=x+1;

clear all;
close all;

fig=1;

nos=256;
amp=1;
t=0:(2.*pi)./(nos.-1):(2.*pi);

sine_w=amp.*sin(t);
figure(fig++);
plot(t,sine_w);
grid on;

number_of_bits=8;
ampl_pp = 2.*amp;

lsb = ((2.^number_of_bits)-1)./ampl_pp;
sine_discrete_signed_tmp = (sine_w.*lsb);
sine_discrete_signed = int8(sine_discrete_signed_tmp);
max(sine_discrete_signed_tmp)
min(sine_discrete_signed_tmp)

figure(fig++);
plot(t,sine_discrete_signed);
grid on;

sine_discrete_unsigned_tmp = ((1.+sine_w).*lsb);
sine_discrete_unsigned = uint8(sine_discrete_unsigned_tmp);
max(sine_discrete_unsigned)
min(sine_discrete_unsigned)

figure(fig++);
plot(t,sine_discrete_unsigned);
grid on;

length = size(sine_discrete_unsigned,2);
sine_unsigned_2thcompl = zeros(1,length);
for(n=1:1:length)
if(0 <= sine_discrete_signed(:,n))
sine_unsigned_2thcompl(:,n) = sine_discrete_unsigned(:,n) .- (2^(number_of_bits.-1));
else
sine_unsigned_2thcompl(:,n) = (2^(number_of_bits.-1)) .+ sine_discrete_unsigned(:,n);
endif
endfor
max(sine_unsigned_2thcompl)
min(sine_unsigned_2thcompl)

figure(fig++);
plot(t,sine_unsigned_2thcompl);
grid on;

yy=(dec2bin(sine_unsigned_2thcompl));

fid=fopen('sine_value.data','wt');
for(n=1:1:size(yy,1))
fprintf(fid, '%s \n', yy(n,:));
endfor
fclose(fid);
display('text file for signal finished');


with only 6 Bits and a stairplot the discrete steps are clearly visible

There are bunch of things happening here.

1. dec2bin and bin2dec aren't great with signed integers. It may be better to manage the 2's complement manually
2. Your sine wave includes +128 which is out of bounds. You either need to manually clip this to 127 or scale the whole sine wave by 127/128 so it's symmetric and going from -127 to + 127
3. Your table is not 256 points long. If you create the argument for the sine, make sure to EXCLUDE 2*pi (since it's duplicates what's already at 0). That's probably the main reason for your asymmetry in your data

Here is a script that produces C code with a max amplitude of 127

%% create an 8 bit sine table

% create a 256 sine table EXCLUDING 2*pi, cap at 127 and round
n = 256;
sineTable = round(127*sin(2*pi*(0:n-1)'./n));

% create 2's complement
sineTable(sineTable < 0) = 256+sineTable(sineTable < 0);

% print it in hex C code
s = sprintf('char sineTable[%d] = {\n',n);
for i = 1:n-1
s = [s sprintf('  0x%02X,\n',uint8(sineTableQuantized(i)))];
end
% last one
s = [s sprintf('  0x%02X};\n',uint8(sineTableQuantized(n)))];
fprintf('%s',s);