Success story with LGT8F328p in linux

Go To Last Post
48 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The board is a TTGO XI LGT8F328P As was reported in other threads, is *mostly* compatible with ATMEGA32, it has built in DAC, internal oscillator at 32Mhz, and high current output ports among other interesting features, so I have been meaning to get my hands on one of them. Now it finally arrived, but I didn't see much information on how to work with it in linux, so I wanted to share my experience.

 

When I first plugged the board to the USB port, its led immediately started to blink. I set my objective of first replicating this blinking. For this I had to find which port the led is connected to. The marking reads "D1" but it looks like a typo and should instead be PB4 (or D12) since in the back you can read "MISO", according to the datasheet.

 

 

 

 

Coding

So I started by creating a blinker test.c

In this one I used the familiar DDRx PORTx macro definitions.

 
test.c :

#ifndef F_CPU
// LGT8F328p is at 32MHz by default with the clock divider set to /8 = 4MHz
#define F_CPU 4000000UL
#endif

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  DDRB = 0xFF;

  while(1)
  {
    // LED toggle
    PORTB ^= 0xFF;
    _delay_ms(500); // wait about half second
  }
}

 

The 328p headers come with a set of handy and self-explanatory macros for dealing with GPIO, the naming is different so grep didn't find a PORTx definition on them. The macros look very convenient so I decided to give them a try, leaving behind the familiar PORTx...

 

 

#ifndef F_CPU
// LGT8F328p is at 32MHz by default with the clock divider set to /8 = 4MHz
#define F_CPU 4000000UL
#endif

// This header can be found in lgt8f328p_sdk_v20170318.rar
// at http://www.logicgreen.io/upload/lgt8fx8p/lgt8f328p_sdk_v20170318.rar
#include "lgt8f328p_gpp.h"

#include <util/delay.h>

int main(void)
{
    gppEnableOutput(GPPB, PALL);

    while(1)
    {
        // LED toggle
        gppToggle(GPPB, PALL);
        _delay_ms(500); // wait about half second
    }
}

Compile
Compiling was done as I usually do for the atmega:

$ avr-gcc -Os -mmcu=atmega328p -c test.c
$ avr-gcc -mmcu=atmega328p test.o -o test.elf
$ avr-objcopy -j .text -j .data -O ihex test.elf test.hex

Edit: It is important to select atmega328p (not just atmega32), in order for avr/*.h headers to provide the correct addresses.

 

Burn to LGT

This board in particular comes with a USB-TO-SERIAL converter (Holtek HT428534)

When you plug in the device you can check it was detected by issuing the following command:  

marcelo@breeze:~$ sudo dmesg  | tail --lines 3
[221276.876707] usb 2-1: new full-speed USB device number 26 using xhci_hcd
[221277.016697] cdc_acm 2-1:1.0: ttyACM0: USB ACM device
[221277.018282] usbhid 2-1:1.2: couldn't find an input interrupt endpoint

The lsusb command reported its vendor and product ids:

$ lsusb
Bus 001 Device 005: ID 147e:1002 Upek Biometric Touchchip/Touchstrip Fingerprint Sensor
Bus 001 Device 004: ID 04f2:b35c Chicony Electronics Co., Ltd
Bus 001 Device 003: ID 0bda:b728 Realtek Semiconductor Corp.
Bus 001 Device 002: ID 8087:8000 Intel Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 002 Device 027: ID 04d9:b534 Holtek Semiconductor, Inc. USB TO UART BRIDGE
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

 

So there is an "ACM device" at /dev/ttyACM0

Let's create a udev rule in /etc/udev/rules.d/99-Holtek-USB-TO-UART.rules so I can use avrdude without root. The file looks like this:

# Holtek USB TO UART converter
ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="b534", MODE="0666"

Reloaded udev rules:

$ sudo udevadm control --reload-rules
$ sudo udevadm trigger

 

Unplug and plug again the device if needed.

 

Finally, the command to burn the code:

$ avrdude -c arduino -b 57600 -F -P /dev/ttyACM0 -p atmega328p -U flash:w:test.hex

That's it, the led was blinking. It's very bright even though it's connected directly to the pin...

 

 

I attach the headers and the translated datasheet, since links to github have been breaking a lot recently...

 

Edited: Corrected misunderstanding with avr/io.h. Added comment to F_CPU in the code and added a reminder about -mcu parameter in avr-gcc.

 

Attachment(s): 

Last Edited: Sat. Aug 24, 2019 - 05:32 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the English datasheet.    Much nicer than syncing Chinese datasheet with a Google English translation.

 

Try filling all 29kB of the available Flash with proper programs.   (via the bootloader)

 

My "red" LGT8F328P boards have bad flash pages.   They do not run at 32MHz properly.

Likewise my "red" LGT8F328D boards.

 

It is always suspicious when you buy boards with chips that have had their markings removed.

 

I have just received a LGT8F328P-TQFP48 Arduino style board.   It appears to have good Flash memory.   I have not done any extensive testing yet.

I have also ordered two green LGT8F328P-TQFP32 Nano style boards.    They have not arrived yet.

 

I would be a lot happier if chips had markings.

I do not care what the price is.    I just prefer to buy genuine chips.   Not QC failures.

 

David.

Last Edited: Tue. Aug 20, 2019 - 02:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

marcelof01 wrote:
The marking reads "D1" but it's a lie
More of a transcription error.  While it's true that it is actually D12 (if you follow the traces on the PCB), and similarly the D0 next to it is actually D11 (PB3/MOSI), I think the D0, D1 is meant to be DO, DI as in 'data in' and 'data out'.  That's a nomenclature often used for peripherals like SD cards.  Whoever drew up the silkscreen layer for the PCB made the error.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Who stocks these chips (the chips, not PCB)---anyone in the USA?

 

 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:
Who stocks these chips (the chips, not PCB)
Electrodragon in Shenzhen

https://www.electrodragon.com/?s=LogicGreen&post_type=product

https://www.electrodragon.com/w/Logicgreen

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:
More of a transcription error.  While it's true that it is actually D12 (if you follow the traces on the PCB), and similarly the D0 next to it is actually D11 (PB3/MOSI), I think the D0, D1 is meant to be DO, DI as in 'data in' and 'data out'.  That's a nomenclature often used for peripherals like SD cards.  Whoever drew up the silkscreen layer for the PCB made the error.

That makes sense! Now I understand.

 

As for the chip markings,I understand they are in the bottom. I didn't have problems with the Flash so far in the pair I bought, even though I didn't precisely follow good practices with ESD... and poked the thing with an analogous ohmmeter... among other mistakes in retrospective. At least it came in a properly sealed anti-static bag.

 

I wonder if it's possible to add the MCU definitions to avr-gcc to make the process more straightforward, maybe copying those sdk files somewhere...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are these chips (not boards) actually viable for product design?   Also, can they be programmed with standard Atmel tools?  

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can install an "LGT Core" to Arduino.   Then you select the appropriate board in the IDE.

 

You have noticed that the pins are marked D0-D13 for the digital pins.  And A0-A5 for the Analog pins.

You can run most Arduino programs if you use the LGT libraries: SPI.h, Wire.h and digitalWrite() etc.

 

Note that EEPROM steals 2kB from the 32kB Flash memory, bootloader takes 1kB.   This is why you only get 29kB for programs.

EEPROM works differently.    Some instructions work with less clock cycles.    ADC and SPI are superior.   And there is hardware Maths support.

 

In other words,   you have to be aware of the hardware differences.

 

I suggest that you start with the Arduino IDE.

When familiar with the hardware,  you can write regular C or ASM in AS7.   (Or appropriate Linux IDE)

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avrcandies wrote:
Are these chips (not boards) actually viable for product design?   Also, can they be programmed with standard Atmel tools?  

 

The boards can only be programed with avrdude because they come with a bootloader. To program the bare chips, I'm guessing you will need the programmer from Logic Green "SWDICE mkII Pro"

https://item.taobao.com/item.htm...

 

edit: and the programmer software will be somewhere in their site that keeps changing URL as if it was an old warez site (oh, I miss the net from 20 years ago...): http://www.lgtic.com

Last Edited: Wed. Aug 21, 2019 - 12:09 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Right, I knew that existed. But the code is a bit shady with fake signatures and such. Does it work for the LGT8F328P too?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:
Does it work for the LGT8F328P too?
Don't know as I didn't browse the source code.

Transparency : am patient for AVR DA-series

https://packs.download.microchip.com/#collapse-Microchip-AVRDx-DFP-pdsc

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I did not know this was a Logic Green support forum!?

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:
I did not know this was a Logic Green support forum!?

 

It's AVRFreaks, right? These chips are AVR.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

It's AVRFreaks, right? These chips are AVR.

How do you figure?

 

It's a bit like asking AMD questions on an Intel forum, isn't it?

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Exactly like that.  I see you had to dig back 6 years to find an example ;-)

 

While I don't have an objection to discussing LGT devices here, I don't own the company.

 

EDIT:  Not >>exactly<< like that.  That's discussing an Intel software product running on an (largely) Intel-compatible processor (albeit from a competitor).  >>This<< thread is discussing a competitor's hardware as a viable replacement for the forum host's hardware.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Wed. Aug 21, 2019 - 03:46 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:
Exactly like that.  I see you had to dig back 6 years to find an example ;-)

 

Actually it took me 5 minutes  https://www.google.com/search?source=hp&ei=qGddXZW0M46VsAeY-ZDgBg&q=site%3Aintel.com+amd

 

Anyway, maybe you are right and Microchip may not like us discussing LGT products, but I'm not on Microchip's side or LGT's side, I'm on my side as user. And everyone knows competition is good for users.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Again, I'm not complaining.

 

However:

joeymorin wrote:
These chips are AVR
... is verifiably false.  At best they are (incompletely) AVR-compatible.

 

;-)

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, I meant AVR as an architecture, in the sense that AMD and Via produce x86 CPUs.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I guess it is a question of licencing. Are these chips just bootleg rip-offs or could it be they have licenced the IPR from Atmel/Microchip? Just as you might discuss Samsung, ST or Atmel/Microchip ARMs on the arm.com site (because they are all licenced producers) I think it would be different if someone had some "ARM clone" they stuck into an FPGA or something that was offering "ARM compatibility" but ARM weren't getting any royalties. So does anyone know if these are a licenced derivative of AVR8? If they are not licenced it does seem to be tantamount to "stealing".

 

(I may ask the Atmel lads "behind the scenes" and see how they feel about this...)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, if you discuss interfacing to a Linear Tech DAC, or Maxim watchdog chip, they might not like that either.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have a question then, because I don't know how it happened historically, but why are there so many 8051 clones?

Does Intel collect royalties from all of them? Did they open the architecture or something like that?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would not get too worried about the "competitor".

LGT is a Chinese company that makes no attempt to sell to the Western market.

 

I suspect that they have designed their own silicon.   It just executes similar instructions and has similar peripherals.

There are some VERY significant differences.

 

As far as I know,   a clever student can create her own MCU core with public CAD tools.

Designing the peripheral hardware and the actual die / wafer is not impossible.

 

Chinese companies are well ahead of "the West" for TFT,  OLED hardware panels and controller chips.

They also seem to have superior technology in several areas.

 

General discussion or comparison of different ARM chips seems fine to me.

It would not be wise to post ST or TI code on a Microchip Forum.

 

8051 cores are used in many ASICs.

 

Are we going to condemn Barnacle for his home-made CPU ?

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:

Are we going to condemn Barnacle for his home-made CPU ?

Only if he starts to muscle in on Microchip's market share ;-)

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk will keep us informed on the state of Barnacle's stock price.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry, I didn't mean to start some kind of trademark war.

 

I think this section is for avr related evboards, maybe it should be moved? There's even a section for general electronics, could be put there.

 

Anyway, LGT, AVR, PIC... I'm not up to date with patent wars, actually I'm still trying to accept the idea that Atmel is now Microchip. Honestly, it doesn't matter to me if it's LGT, Atmel. Microchip or GigaDevices or CS or HolyChip... as an engineer, and as a human being, I'm grateful to be able to build on the work of others and I'm more than happy that others can also build upon whatever I can manage to contribute. Nobody can claim the ownership of "1"s or "0"s, it's forced and archaic to talk about "property" when we talk about technology. I prefer to leave the suing and speculation to lawyers and stock people. Big companies have done much good in R&D but also have done much bad: delayed feature release, planned obsolescence, stranglement of innovation in name of profit... Who knows, maybe a competitor is exactly what we need?

 

Now to what is interesting

 

I've finally got around trying out the DAC of the chip. 

 

Here is the result:
 

#ifndef F_CPU
#define F_CPU 32000000UL
#endif

#include "lgt8f328p_spec.h"
#include <util/delay.h>
#include <avr/power.h>
#include <math.h>

int main(void)
{
  // set div to /1 (default /8), so speed increases from 4Mhz to 32Mhz
  clock_prescale_set(clock_div_1);

  // DACEN: enable DAC
  // DAOE: let the DAC output reach DAO port (PD4)
  DACON = (1<<DACEN) | (1<<DAOE);

  unsigned char x = 0;
  unsigned char y = 0;
  char dir = 1;
  char ylist[256]; 

  // Create fancy waveform
  do {
    if (x<128) { // first half
      // Create "M" part of waveform
      if (x<64) dir=-1;
      else dir = 1;
      y+=dir;
    } else { // second half
      // Create inverted "U" part of waveform
      y = sin((x - 128) * 3.1415 / 128.0) * 128;
    }
    ylist[x] = y;
  } while(255 > x++);

  // Replay the waveform
  while(1) {
    DALR = ylist[x++];
    _delay_us(1.3162 *  // delay function compensation since SBIW uses just 1 cycle in this MCU
        10000.0 / 256);// 10ms per full cycle = 100Hz
  }
}

 

 

Now if I let this run without a delay, the timing is:

* at 32MHz clock the frequency I get ~11.35KHz

* at 4MHz clock the frequency I get ~1.43KHz

 

I wonder if it's possible to make it run faster...

 

Edit: With a simple DALR toggle:

 

while(1) {
    DALR ^= 0xFF;
}

I get the following results:

 

* at 32MHz clock the frequency I get ~2.66MHz

* at 4MHz clock the frequency I get ~335KHz

 

Again the numbers keep direct proportionality with the MCU clock speed.
At first I thought it might be some kind of DAC electrical limitation but it seems to be more like the array "ylist" access is slow (relative to my fantasies :p).

Last Edited: Sat. Aug 24, 2019 - 07:27 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

at 32MHz clock the frequency I get ~2.66MHz

Well you only have 2 data points to cycle through...so it will do so very fast.

Think, if you had 23456 points, it would take a much longer time to cycle through all of them (even if the lookup was infinitely fast).  

You could create a wave using fewer points and/or perhaps speed up the lookup.  You can only spit out so many points per second.

try increasing x by 2...twice the freq!

 

If you force the table beginning address to be a nice boundary( ex: 0x0200), then the high address byte can remain constant (and never need updated for each x++), and just the low address byte wraps around using a simple inc.  

The tricky part is telling the compiler you wish to do so.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sat. Aug 24, 2019 - 08:19 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  uint8_t *p = ylist;
  uint8_t cnt = 0;
  while (1) {
      if (--cnt == 0) p = ylist;
      DALR = *p++;
  }      

With -O2 you get:

      DALR = *p++;
000000A6  LDD R25,Z+0		Load indirect with displacement
000000A7  STS 0x00A1,R25		Store direct to data space
000000A9  ADIW R30,0x01		Add immediate to word
      if (--cnt == 0) p = ylist;
000000AA  SUBI R24,0x01		Subtract immediate
000000AB  BRNE PC-0x05		Branch if not equal
000000AC  MOVW R30,R28		Copy register pair
000000AD  ADIW R30,0x01		Add immediate to word
000000AE  RJMP PC-0x0008		Relative jump

The typical loop is 9 cycles on an AVR.   You will have to check the LGT instruction timing.

 

As avrcandies says: place ylist on a page boundary.

loop:
    LDD  R25,Z+0     //2 [1]
    SUBI R30,0x01    //1 [1]
    STS  0x00A1,R25  //2 [2]
    RJMP loop        //2 [1]

This loop is always 7 cycles for an AVR.  5 cycles for LGT

Wait a few minutes and we will get a Scandinavian solution.

 

32000000 / (256 * 4) is 31.25kHz   //LGT

32000000 / (256 * 7) is 17.86kHz   //ASM

32000000 / (256 * 9) is 13.89kHz   //-O2

32000000 / (256 * 13) is 9.62kHz   //-O1

 

Using AS7 Simulator.

 

I will try the DAC in an ATmega4809 and an ATtiny817  (when I return from trolley bashing)

 

David.

 

Edit.   Corrected the LGT STS execution cycles.   LGT ST (store indirect) is a one-cycle instruction.

Last Edited: Sun. Aug 25, 2019 - 08:24 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The first Atmel cpu's like the AT89C2051 was "real" Intel chips, meaning that Atmel payed royalties to Intel.

For atmel it was a fast way to get into CPU marked (remember Atmel was a memory company). 

As I remember there was some limitations to what kind of 8051's Atmel was aloud to make (not competed with Intel).

So to avoid that and paying royalities Atmel desided to make the AVR's a Norwegian design (ownership between designers and Atmel I don't know).

Then later Atmel also made faster 8051 chips (that is NOT a intel design), I'm not sure but I think that part came in house with ES2.  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I built for a Tiny817 -O2.  Typical loop is 9 cycles.   However you could use LDD R25,Z+ and remove the ADIW R30 instruction.

As avrcandies pointed out,  it is difficult to persuade the C compiler to use post-increment.

      DAC0_DATA = *p++;
0000007D  LDD R25,Z+0		Load indirect with displacement 
0000007E  STS 0x0681,R25		Store direct to data space 
00000080  ADIW R30,0x01		Add immediate to word 
      if (--cnt == 0) p = ylist;
00000081  SUBI R24,0x01		Subtract immediate 
00000082  BRNE PC-0x05		Branch if not equal 
00000083  MOVW R30,R28		Copy register pair 
00000084  ADIW R30,0x01		Add immediate to word 
00000085  RJMP PC-0x0008		Relative jump 

The mega4809 does not have DAC

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

An excellent opportunity to show off my secret technique, compile time generation of lookup tables using C++ in avr-gcc :)

Requires C++14 syntax to be enabled (-std=gnu++14). The executable is much smaller, because math libraries are no longer needed at run time.

 

#define F_CPU 32000000UL

#include <util/delay.h>
#include <avr/power.h>
#include <avr/pgmspace.h>
#include "lgtx8p.h"

// We need to return arrays, but C/C++ can't do it directly, so it's wrapped in a structure
typedef struct {
	uint8_t data[256];
} wave;

// Fancy function
constexpr uint8_t fancy_wave_function (uint8_t x) {
	return x < 128 ?
  		// first half
      	// Create "M" part of waveform
    	( x < 64 ? 255 - x : x + 128 ) :
    	// second half
    	// Create inverted "U" part of waveform
    	( __builtin_sin((x - 128) * 3.1415 / 128.0) * 128 );
}

// Linear function
constexpr uint8_t linear_wave_function (uint8_t x) {
	return x;
}

// Sine function
constexpr uint8_t sine_wave_function (uint8_t x) {
	return ( 128 + __builtin_sin(x * 3.1415 / 128.0) * 128 );
}

// Function that returns a 256 byte array, and takes a wave function as argument
constexpr wave make_wave( uint8_t wave_function (uint8_t) ) {
	wave tmp = {0};
	for (int i = 0; i < 256; i++) {
		tmp.data[i] = wave_function (i);
	}
	return tmp;
}

// Create wave array
const PROGMEM wave my_wave = make_wave ( fancy_wave_function );
// const PROGMEM wave my_wave = make_wave ( linear_wave_function );
// const PROGMEM wave my_wave = make_wave ( sine_wave_function );

int main(void)
{
  // set div to /1 (default /8), so speed increases from 4Mhz to 32Mhz
  clock_prescale_set(clock_div_1);

  // DACEN: enable DAC
  // DAOE: let the DAC output reach DAO port (PD4)
  DACON = (1<<DACEN) | (1<<DAOE);

  unsigned char x = 0;

  // Replay the waveform
  while(1) {
    DALR = pgm_read_byte( &my_wave.data[x++] );
    _delay_us(1.3162 *  // delay function compensation since SBIW uses just 1 cycle in this MCU
    	10000.0 / 256);// 10ms per full cycle = 100Hz
  }
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
The mega4809 does not have DAC
An 8b internal DAC (IO register AC0.DACREF)

edit : forthcoming AVR DA-series

https://www.avrfreaks.net/forum/what-are-avr28da128-avr32da128-avr48da128-avr64da128#comment-2755366

 

"Dare to be naïve." - Buckminster Fuller

Last Edited: Sun. Aug 25, 2019 - 02:40 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is essentially the same speed limit as you'd get from a DDS ---you can look there for "tricks".  However, it appears our codes are as short as you can get.

 

The 0th byte needs stored at a 0xNN00  address

loop: LD XL, Z ;get data pointed to by ZH:ZL   ...avr8L can get from ram in 1 cycle, flash is ....2 cycles

       sts DACREG, XL   ;update the dac ...1 cycle 
        
       inc ZL     ;just let low byte cycle round & round trough 256 locations, ...1 cycle

       rjmp loop   ;keep going  ....2 cycles

 

is that 5 cycles for am avr8L series?  freq is 32e6/5/256= 25KHz  MAX

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for the hints!

 

int main(void)
{
  //  set div to /1 (default /8), so speed increases from 4Mhz to 32Mhz
  clock_prescale_set(clock_div_1);

  // DACEN: enable DAC
  // DAOE: let the DAC output reach DAO port (PD4)
  DACON = (1<<DACEN) | (1<<DAOE);

  unsigned char x = 0;
  unsigned char y = 0;
  char dir = 1;

  // I assign my own memory wherever I want, OS is not at home!
  unsigned char * ylist = (char *) 0x100;

  // Create fancy waveform
  do {
    if (x<128) { // first half
      // Create "M" part of waveform
      if (x<64) dir=-1;
      else dir = 1;
      y+=dir;
    } else { // second half
      // Create inverted "U" part of waveform
      y = sin((x - 128) * 3.1415 / 128.0) * 128;
    }
    *ylist++ = y;
  } while(x++ < 0xFF);

  // Replay the waveform
  asm volatile ( " clr r30 ; ZL is 0\n"
                 " ldi r31,0x1 ; ZH is 1 (data address base is 0x100) \n"
                 ".loop: \n"
                 " ld r25, Z ; get byte from address at Z\n"
                 " inc r30 ; increment ZL and let it roll :) \n"
                 " sts 0xA1, r25 ; DALR is 0xA1 \n"
                 " rjmp .loop \n");

}

I manually specify the pointer value... Is there a more civilized way of doing page alignment? I haven't found much information about it, now I don't have anything else in memory so it wasn't much trouble.

 

Also, avr-gcc doesn't accept lo8(ylist) or hi8(ylist), so I also wrote constants there, as well as in the sts instruction for DARL register address... is it the price I have to pay for mixing C and ASM or is there a more elegant way?

 

PS: the code above generates the wave at 24.99KHz

Last Edited: Sun. Aug 25, 2019 - 07:08 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for the hints!

Does it work? What speed do you get? 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for the hints!

Does it work? What speed do you get? 

 

 

It works. The speed was 24.99KHz.

 

I changed it to use st (once cycle) instead of sts (two cycles) and now I get 31.2KHz :

 

  // Replay the waveform 
  asm volatile ( " clr r30 ; ZL is 0\n"
                 " ldi r31,0x1 ; ZH is 1 (data address base is 0x100) \n"
                 " ldi r28,0xA1 ; YL will contain DACL\n"
                 " clr r29 ; YH is 0\n"
                 ".loop: \n"
                 " ld r25, Z ; get byte from address at Z\n"
                 " inc r30 ; increment ZL and let it roll :) \n"
                 " st Y, r25 ; DALR is 0xA1 \n"    
                 " rjmp .loop \n");

 

I think the next level is to hardcode a lot of "st Y, <constant>" but then it's not flexible any more. It meets my requirements for now, except for the code aesthetic part.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


marcelof01 wrote:
I changed it to use st (once cycle) instead of sts (two cycles) and now I get 31.2KHz

 

That was interesting as an optimization exercise, but the LGT DAC is rated @ 500k samples per second, so at this speed it's way out of spec (about 8M samples per second).

But since we are testing limits, I overclocked the MCU by setting RCMCAL = 255, obtaining 42.5kHz (this means the MCU is running at > 43MHz). The distortion is massive:

 

 

(yeah, we have the same scope smiley)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You are arbitrarily setting a pointer to 0x100 then writing through it. That's the usual location of .data then .bss - are you really saying this program has no .data nor .bss variables?

 

Why not either malloc or create a fixed array? (There are data attributes for alignment)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think the next level is to hardcode a lot of "st Y, <constant>" 

Sadly, that's not possible, it can only store from a register (which contains the constant) 

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you can afford to tie up the Y register it gives you a worthwhile improvement on your loop cycles.

 

Most apps don't really care.   But if you are writing large quantities of data to a non IN/OUT peripheral register it is dramatic.

The LGT instruction cycles are impressive.   Much better than the modest Xmega, AVR8X improvements.

 

Note that peripherals like SPI, DAC, ADC, ... have timing constraints.   So your effort might be in vain.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

LGT DAC is rated @ 500k samples per second, so at this speed it's way out of spec

Could you point me to the specs? I could not find any actually, in the data sheet there are specs for the ADC and the PWM but not for the DAC or at least I can't find them... The Attiny's DAC is rated at 350Ksps absolute max so that would be something worth mentioning.

 

The distortion shows the actual raise time and fall time, aymmetric at that scale. This may be the reason it's advertised as a voltage reference and input for the comparator and not multi-KHz waveform generation. Maybe it was created with the audible spectrum in mind? It would be interesting to make it drive a small speaker, I can think of some interesting projects.

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I thought I saw that spec in some translated datasheet version, but now I can't find it :(

 

Anyway, the LGT DAC is just a resistor ladder, it doesn't have a buffer, therefore it's driving ability is nonexistent. The (apparently discontinued) LGT8F328D had internal opamps that could possibly be used as buffer to the DAC. (edit: actually not, because their output seems to be unavailable externally).

 

I will attach the original datasheet for the D version.

Attachment(s): 

Last Edited: Mon. Aug 26, 2019 - 11:10 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for that document, actually there it says the output of the two DACs are available at DAO(PD4) and DAO1(PE5). I wonder why the new version has only one... (and it seems to be the new version as there's this document for migration from LGT8F328D to LGT8F328P) A lot of things improved but the two dacs became only one. There's also the lgt8f684p with two buffered (6bit) DACs but it's not flash I think

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I dug out my 40 year old 10MHz Analog scope.

 

The LGT8F328P DAC waveform is crap above 1.3kHxz

The ATtiny817 DAC waveform is nice and clean.

 

I have ordered a pair of replacement 10X probes.    This should make the old scope "usable".

 

I have often thought about buying a modern scope.   But doubt that it would get used much.     

 

Would a Rigol DS1054Z be a wise choice?

 

I will play with LGT8F328D and LGT8F328P DAC tomorrow.   I suspect that they will be much happier with less frequent samples e.g. DDS style.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
Would a Rigol DS1054Z be a wise choice?

 

From what I gather, that one and the Siglent SDS1104X-E are considered the best options for this class. Which one is better seems to be the source of endless debate https://www.eevblog.com/forum/te...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why do they makes it so hard to get a datasheet....don't they plan to sell chips?  That is a real advantage of Microchip/Atmel...readily available documentation. some support, & plenty of distributors with stock.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Contest/giveaway of embedded goodies (The Ganssle Group)

August 2019 Giveaway

This month's giveaway is a slightly-used (I ran it for review [Siglent's SDS 2000X Oscilloscopes] purposes) 300 MHz 4-channel (including 16 digital channels) SDS 2304X scope from Siglent that retails for about $2500.

SDS2304X scope giveaway

The giveaway will close at the end of August, 2019.

[rules]

[entry]

 

edit : strikethru

 

"Dare to be naïve." - Buckminster Fuller

Last Edited: Tue. Aug 27, 2019 - 04:19 AM