rosco-m68k / rosco_m68k Goto Github PK
View Code? Open in Web Editor NEWDesign, documentation and software for the Really Old School Computer (M68K)
Home Page: https://rosco-m68k.com
License: Other
Design, documentation and software for the Really Old School Computer (M68K)
Home Page: https://rosco-m68k.com
License: Other
When calling the Easy68k clear screen TRAP function with FW1.1b2, the back buffer is not cleared correctly.
This causes previous video memory contents to be displayed after the screen is "cleared".
Cursor positioning and continued operation is not affected.
In the 1.1 and 1.2 firmwares, it would be nice to use a better-compressing implementation of DEFLATE/INFLATE - e.g. https://github.com/keirf/Amiga-Stuff/tree/master/inflate
In the current schematic (and revision 0 board design) the address lines A1-A5 are incorrectly connected to MFP register select RS5-RS1 (I.e they are reversed).
This needs two fixes:
Correcting the schematic is self-evident.
The software fix will involve changing the register addresses in equates.S to reverse bits 1-5. This change will apply only to boards made from the current (pre-schematic-fix) design.
Thanks to Henk Gooijen for this suggestion:
So, for R3 you could remove the 7401 and the 8 MHz Xtal, and replace it with a canned 10 MHz oscillator. Further, remove the 7493 and replace it with a 4 MHz canned oscillator
This would get rid of two increasingly hard-to-find and expensive 7400s from the design and significantly increase flexibility. We should definitely do this!
(Plus the current clock is barely in-spec, so there's that too...)
The terminal exception handlers (BUS ERROR, ADDRESS ERROR and ILLEGAL INSTRUCTION) currently flash the red LED in a different pattern to indicate the fault condition.
They do not initialise the GPIOs to the appropriate state before doing this. In cases where the programmer has changed the state of the GPIOs to enable efficient use of the MFPs GPIO port, this may result in non-visible flashing in a crash situation.
The exception handlers should set the appropriate GPIO to OUTPUT (and initialise the GPIO port to a known state) before entering into the terminal loop.
The ROM code for the Easy68K trap function #7 (CHECKINPUT) is still directly talking to the MFP.
Instead, it should use whichever UART is the default.
This will probably mean adding a new function to the EFP to support.
First: Just pulled your changes from github.
Normally my git knowledge stops at making clones, but I have intention of learning more of git.
paul@dualcore:~/projects/kicad/zzz_prut/rosco_m68k$ git pull
remote: Enumerating objects: 23, done.
remote: Counting objects: 100% (23/23), done.
remote: Compressing objects: 100% (20/20), done.
remote: Total 23 (delta 5), reused 13 (delta 3), pack-reused 0
Unpacking objects: 100% (23/23), done.
From https://github.com/roscopeco/rosco_m68k
4ef7063..7de5cf8 master -> origin/master
Updating 4ef7063..7de5cf8
Fast-forward
.gitignore | 1 -
README.md | 69 ++++-----
design/r0/r0-kicad-import/rosco_m68k.pro | 43 ++++++
design/r1/kicad/rosco_m68k.pro | 249 +++++++++++++++++++++++++++++++
images/r1-populated.png | Bin 0 -> 3593232 bytes
5 files changed, 322 insertions(+), 40 deletions(-)
create mode 100644 design/r0/r0-kicad-import/rosco_m68k.pro
create mode 100644 design/r1/kicad/rosco_m68k.pro
create mode 100644 images/r1-populated.png
I can now work with it as a normal KiCad project.
First thing I noticed is that footprints for the memory chips were not in the schematic.
You can easily fix this by:
Pcbnew / File / Export / Footprint association (.cmp) File
Then go back to Eeschema, and import that file:
Eeschema / File / Import / Footprint Association File
I've also used your project as an example of "vector buses" in:
https://forum.kicad.info/t/lots-of-nets-how-to-organize/21967/11
When loading large BIN files from SDHC cards, loading consistently fails. Observed with Kingston 32GB card.
rosco_m68k: SD card file menu - Xark (Oct 13 2020 20:15:09)
[ 21K] A - roscode1.bin [522K] B - myprogram.bin
Press A-B to run, SPACE to reload, RETURN for prompt (others exit): B
Loading "/myprogram.bin"........................
*** Load error
When loading via Xark's menu loader, this always happens (for me) at $60000 bytes loaded.
Interestingly, when loading directly (in the firmware) it seems to occur at $30000 instead.
On Ubuntu 20.04
Following Toolchain.md using manual source install method.
GCC 7.5.0 install successful per instructions.
firmware build fails at:
`
$ BIGROM=true make clean all
make -C stage2 clean
make[1]: Entering directory '/home/quarterturn/Documents/rosco_m68k/code/firmware/rosco_m68k_v1.2/stage2'
rm -f init2.o common.o serial.o machine.o main2.o kermit/kermit.o kermit/kermit_support.o sdfat/gpio.o sdfat/bbspi.o sdfat/bbsd.o sdfat/load.o sdfat/fat_io_lib/fat_access.o sdfat/fat_io_lib/fat_cache.o sdfat/fat_io_lib/fat_filelib.o sdfat/fat_io_lib/fat_format.o sdfat/fat_io_lib/fat_misc.o sdfat/fat_io_lib/fat_string.o sdfat/fat_io_lib/fat_table.o sdfat/fat_io_lib/fat_write.o loader2.bin loader2.bin.zip loader2.bin.zip.o loader2.map
make[1]: Leaving directory '/home/quarterturn/Documents/rosco_m68k/code/firmware/rosco_m68k_v1.2/stage2'
rm -f bootstrap.o lzgmini_68k.o decompress.o ansicon.o trap14.o main1.o easy68k/syscalls_asm.o easy68k/syscalls.o video9958/vdpcon.o video9958/font.o rosco_m68k.rom rosco_m68k_odd.rom rosco_m68k_even.rom rosco_m68k.map
vasmm68k_mot -Felf -m68010 -quiet -o bootstrap.o bootstrap.S
vasmm68k_mot -Felf -m68010 -quiet -o lzgmini_68k.o lzgmini_68k.s
vasmm68k_mot -Felf -m68010 -quiet -o decompress.o decompress.S
vasmm68k_mot -Felf -m68010 -quiet -o ansicon.o ansicon.S
vasmm68k_mot -Felf -m68010 -quiet -o trap14.o trap14.S
m68k-elf-gcc -c -std=c11 -ffreestanding -nostartfiles -Wall -Wpedantic -Werror -Iinclude -mcpu=68010 -march=68010 -mtune=68010 -Os -fomit-frame-pointer -mno-align-int -mno-strict-align -DEASY68K_TRAP -DVIDEO9958_CON -Ivideo9958/include -o main1.o main1.c
make: m68k-elf-gcc: Command not found
make: *** [Makefile:66: main1.o] Error 127
`
here's all I have in my home opt directory path:
`
~/opt/cross/bin$ ls
m68k-elf-addr2line m68k-elf-c++filt m68k-elf-ld m68k-elf-objcopy m68k-elf-readelf m68k-elf-strip srec_info
m68k-elf-ar m68k-elf-elfedit m68k-elf-ld.bfd m68k-elf-objdump m68k-elf-size srec_cat vasmm68k_mot
m68k-elf-as m68k-elf-gprof m68k-elf-nm m68k-elf-ranlib m68k-elf-strings srec_cmp
`
make install for gcc fails with:
`
Libraries have been installed in:
/home/quarterturn/opt/cross/libexec/gcc/m68k-elf/7.5.0
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
make[2]: Nothing to be done for 'install-data-am'.
make[2]: Leaving directory '/home/quarterturn/Downloads/m68k-toolchain/build-gcc-7.5.0-m68k/lto-plugin'
make[1]: Leaving directory '/home/quarterturn/Downloads/m68k-toolchain/build-gcc-7.5.0-m68k/lto-plugin'
make[1]: Entering directory '/home/quarterturn/Downloads/m68k-toolchain/build-gcc-7.5.0-m68k/gcc'
make[1]: *** No rule to make target 'install'. Stop.
make[1]: Leaving directory '/home/quarterturn/Downloads/m68k-toolchain/build-gcc-7.5.0-m68k/gcc'
make: *** [Makefile:4301: install-gcc] Error 2
`
code/libs/start_serial
should clear BSS before calling kmain, however this is not happening correctly.
Xark spotted that the code in https://github.com/rosco-m68k/rosco_m68k/blob/release/revision-1.2/code/software/libs/src/start_serial/kinit.c is likely off-by-one. It should probably be e.g.
for (int *bss = _bss_start; bss <=_bss_end; bss++)
*bss = 0;
Currently, the trap handlers are allowed to trash their arguments. Sometimes this works well (e.g. string pointing to next in an array) but often it is most annoying (e.g. trashing the function code, meaning it must be set again when e.g. printing multiple buffers consecutively).
Currently, the glue logic CUPL code (in /pldcode/glue/GLUE_LOGIC.PLD
) uses FC0, FC1 and FC2 to generate the IACK signal. On MC68010 this is not always true - breakpoints also occur with those three lines high.
The difference on this processor is determined by reading address lines 16-19 - during IACK these four lines will also be high, while in a breakpoint situation they will not.
This is not currently a problem but worth investigating if there's ever a desire to do hardware breakpointing.
(See #7 for original report)
In the current schematic (and revision 0 board design) the address lines A1-A5 are incorrectly connected to MFP register select RS5-RS1 (I.e they are reversed).
A software fix has been implemented. The schematic/board still needs to be fixed before the next revision is manufactured.
Thanks to Henk Gooijen for this suggestion!
You could add an LED on the RESET using IC9D. Can probably be patched on the R2 board. IC9D pin 11 and pin 12 disconnect from GND (IF that is possible ...). If possible, then connect pin 11 and pin 12 to pin 4. Disconnect LED3 from the NE555 (pin 3) and connect the LED3 (anode) to IC9 D pin 13).
When the previous run leaves an incomplete line, the logo is messed up on reset because it starts on the same line.
Add a CRLF to the start of the logo to fix this.
I wanted to look around this project (at the moment your store is unfortunately closed) and tried following the tool-chain install documentation on
https://rosco-m68k.com/docs/toolchain-installation
However for my linux mint install this proved incomplete. The one-liner for installing brew works, but afterwards I could not use brew.
The brew documentation on https://docs.brew.sh/Homebrew-on-Linux lists 4 additional lines for getting brew added to the path. However even that fails to mention that you need to log off and on again for it to work.
Maybe this is just something with my linux mint install, but it is pretty much default. So I thought I mention it here.
The current address decoder creates a 256KiB memory hole between 0xF00000-0xF40000
.
Decide whether this is worth fixing. If it is, raise a ticket to fix. If not, close "won't do".
This would require HW changes, so tagging it for r2.
The system timer tick (driven by MFP timer C) is incorrectly running at 200Hz. It should be 100Hz.
This is because the crystal from which the timers are derived had it's frequency doubled after r0, but the bootstrap code that sets up Timer C has never been updated.
200Hz is high and has a negative (if slight) impact on system performance. Additionally, the upticks counter (which is supposed to be hundredths of a second) in FW 1.1 and 1.2 is incorrect.
This is not an issue for FW 1.01 (as it does not track upticks), but should be fixed in FW1.1 and 1.2 (and beyond).
Additionally the counter that drives the I0 flash will need to be adjusted as we want to keep the existing ~1Hz flash.
The ehBASIC input routine is still using input routines that are hardcoded to the MFP.
This should be fixed so they use the firmware IO routines.
The glue logic (IC5) currently defines IACK as:
/IACK = A17 * FC0 * FC1 * FC2
This is not correct for CPUs MC68020 and up - for those CPUs, A17 is high to indicate a Coprocessor CPU Cycle.
For upward compatibility, this should be changed to use either A18 or A19.
(TODO: Check what later CPUs output on these pins for IACK cycles - it may be that we need multiple pins in the A16-A19 range, and if so, probably a bigger GAL...)
The glue logic GAL should emulate open-collector behaviour for DTACK by tri-stating the pin, with enable being driven by DTACK being low. A pull-up should then be applied to DTACK to give correct behaviour.
Hardware changes required - should be done for revision 1.2 or 2. Also need to investigate the impact on current run of V9958 boards which do not manage DTACK (should be fixable with a small jumper modification to pull DTACK low when VDP CS goes low).
Since recent work to integrate libm
from Newlib, many of the examples (memcheck, adventure, etc) no longer build on the develop branch.
$ make
vasmm68k_mot -Felf -m68020 -quiet -DROSCO_M68K -o funcs.o funcs.S
m68k-elf-ld -T ../libs/build/lib/ld/serial/rosco_m68k_program.ld -L ../libs/build/lib -Map=memcheck.map -L/usr/local/Cellar/gcc-cross-m68k@10/10.2.0/lib/gcc/m68k-elf/10.2.0/m68000/ -L/usr/local/Cellar/gcc-cross-m68k@10/10.2.0/lib/gcc/m68k-elf/10.2.0/../../../../m68k-elf/lib/m68k-elf/10.2.0/m68000/ -L/usr/local/Cellar/gcc-cross-m68k@10/10.2.0/lib/gcc/m68k-elf/10.2.0/../../../../m68k-elf/lib/m68000/ kmain.o funcs.o -o memcheck.bin -lprintf -lcstdlib -lmachine -lstart_serial -lgcc
kmain.o: In function `count_rom_size':
kmain.c:(.text+0xb2): undefined reference to `printf'
kmain.o: In function `build_memory_map':
kmain.c:(.text+0x1f8): undefined reference to `printf'
kmain.c:(.text+0x2b6): undefined reference to `printf'
kmain.c:(.text+0x348): undefined reference to `printf'
kmain.c:(.text+0x366): undefined reference to `printf'
kmain.o:kmain.c:(.text+0x450): more undefined references to `printf' follow
make: *** [memcheck.bin] Error 1
Reverting these changes in develop but keeping them in a branch so this can be fixed.
The output lines from the address decoder should not be tristate. There are no pull resistors on these lines, and in any event it is expected by expansions that they always be driven - there is no value in expansions driving these lines directly, rather they should rely on the decoder to correctly select the memory space in use.
Thanks for RTS4E75 for the idea and testing of this.
If r2 board is sticking with 28-pin ROMs, the usable capacity for those ROMs could be expanded by connecting pins 1 and 26. On larger members of the AT28C family (AT28C256 for example) these pins A14 and A13 respectively. This would allow drop-in replacement for ROM size up to 64KB and is verified to still work with the AT28C64B parts currently in use.
When doing this remember that the address pins on the ROMs are off-by-one WRT the CPU lines as the CPU doesn't have an A0 (CPU A14 maps to ROM A13 etc).
Currently, the trap handlers are allowed to trash their arguments (and this is documented). However, some of the handlers also trash registers that are not used as arguments, for example A0
is trashed by TRAP 15 function 14. This is annoying (to say the least) and should not happen.
See also: #164
@XarkLabs discovered that DTACK operation is incorrect on r1 boards with r1.1 GAL code.
The incorrect behaviour can be seen in the trace below - note that, when IOSEL is asserted for IO accesses, DTACK does not go high as it should. This is causing the CPU to proceed faster than the MFP can correctly handle, and means that IODTACK is never asserted by the MFP (due to it's CS being deasserted by the premature end-of-cycle).
The problem is due to incorrect precedence in the logic equations for IC5. This should be fixed on the 1.1 branch. This also needs to be investigated in 1.2 to ensure we do not have similar issues.
Due to the special-case handling of IACK cycles, it's worth noting that IACK functions correctly.
A fix must not change the behaviour externally (especially for EXPSEL accesses) and it is desirable to retain the existing 'normally-asserted' DTACK behaviour if possible.
The DS line of the MFP is incorrectly asserted at all times. This causes bus contention when working with even IO addresses and prevents writing to certain registers from working as it also trashes MFP registers at the following odd address.
The problem is in the glue logic:
/MFPDS = /LDS + IACK
Should be:
/MFPDS = /LDS + /IACK
This is a minimal-impact fix. Hotfix for release/revision-1.01 (and release a bulletin for existing users).
Due to the software switching to the divide-by-sixteen mode on the UART receiver, the maximum baud that can be achieved with the current specification is 4800 bps. This can be increased to 9600 bps by replacing Q1 with a 3.6864MHz part.
Farnell part 9712909 (IQD FP's LFXTAL003263) is a suitable drop-in replacement and does not require any other changes.
With this substitution the firmware will double the baud rate to 9600 without modification.
This is probably the highest (standard) speed possible with /16 mode on the MFP without moving to an external clock, due to its maximum frequency specification of 4MHz, and requirement that all timers use at least a /4 prescaler.
In tests 14400 was achieved and found stable, however support is variable in supporting hardware (e.g. USB-Serial adapters) and software (e.g. Minicom).
When ehBASIC is being used with 1.1 or 1.2 ROMs and output is going to the V9958 text console, random carriage-returns are inserted into the output. For example, in this screenshot a CR was output halfway through typing in line 10, however the subsequent LIST shows that this CR is not actually inserted into the line.
(Hardware issues have been ruled out, the screenshot above is from MAME, though this also happens on real hardware).
I suspect this is an issue in the ehBASIC echo routine. If that doesn't turn up anything, another place to look might be the V9958 console driver in vdpcon.S
(specifically, is there a character it shouldn't print?)
The CUPL code for the address decoder contains an error that causes IO space to incorrectly extend from 0xF00000-0xFBFFFF
instead of the desired 0xF80000-0xFBFFFF
. This is wasting half a megabyte at the top of the address space.
The current code for IOSEL
is:
!IOSEL = IACK & !A18 & A20 & A21 & A22 & A23;
Where it should actually be:
!IOSEL = IACK & !A18 & A19 & A20 & A21 & A22 & A23;
(Notice that the fixed version includes A19 in the equation).
The current timing of IODTACK -> DTACK is not robust enough to support IO devices that have slow tear-down times at the end of the read cycle. Specifically, devices that cannot tristate the bus quickly enough when AS is de-asserted can cause the following bus cycles to fail due to contention.
This is because, after the CPU de-asserts AS, it waits for the device to de-assert DTACK before proceeding. However, the glue logic in IC5 incorrectly drops DTACK immediately as AS is de-asserted due to the address decoder de-asserting IOSEL. This means that, immediately on de-asserting AS, DTACK is de-asserted also and the CPU continues with the next bus cycle.
Unfortunately, this means that no matter whether the IO device continues to assert DTACK the CPU will not see it asserted. In cases where the device is still in process of tristating e.g. the data bus, this can cause contention on the next read and cause garbage to be read.
It's worth noting that this is only really a problem when the bus is driven by microcontroller devices - most hardware devices tristate their bus pins virtually immediately when their CS is de-asserted. In the microcontroller case, it requires careful code design to ensure that the bus cycle is timed appropriately for the CPU.
It's also worth noting that this doesn't place any speed requirements on the actual read - the CPU will respond appropriately to DTACK during the read cycle - this problem only manifests at the end of the cycle.
In practice this means that an Arduino, for example, will have to be programmed with direct port access at least for the end-of-cycle, as pin manipulation via the Arduino SDK (digitalWrite
et al) is too slow for this purpose in all but the most trivial case (e.g. a single pin being tristated).
Did you change something? I peeked in the code (firmware) and _SDB_MEM_SIZE ($414) seems the real end of memory value. The value on $0 gives the top of internal RAM. Xarks sdfat_menu uses the INITIAL_STACK value to determine the size of memory.
The current board has a custom layout for the UART header. For ease of use with readily-available FTDI cables and adapters this should be replaced with the standard 6-pin layout found on those cables.
Somewhere along the line the linkage for the POC kernel and programs has been broken, and these are no longer being linked with the .text section relocated to $1000.
Instead, all code stays at $28000 onward, and the copying in init.S
is pointless.
The revision zero board has pin identifiers for expansion pins 1 and 64 on the silkscreen.
The pin one identifier is correct, but the pin 64 identifier is incorrectly attached to pin 2. Pin 64 is actually at the bottom right of the connector.
ACs:
With new DTACK handling in current develop (for 1.2 board) we will need two things:
I just cloned your project because I am curious what you made of it in the mean time.
Then I discovered that the KiCad project file is missing. Without it KiCad can not be opened in project mode and the link between schematic and PCB is broken. The most logical explanation is that you forgot to put this file in git.
I also saw you entered blue text strings into the title block:
These texts should be added via:
"Eeschema / File / Page Settings"
In the RX_ERROR_HANDLER:
routine (in /firmware/rosco_m68k_v1/base_servers/serial_isr.S
), the arguments passed to the C function handleRxError
are not correctly cleaned up (required since -mrtd is not used in this codebase). This will cause the registers to be 'restored' to incorrect value and probably lead to a crash.
Need to look in to the GCC M68K ABI to see how these (byte-sized) arguments should be properly passed (suspect as a uint32) and then make sure they're cleaned up properly after the function call.
For some reason, the PCB pads on U1-U4 and IC8 are smaller than the other pads. Soldering would be easier if these pads were the same size as the pads on the other ICs. This should be a simple matter of changing the footprint (and probably rerouting some of the traces) - the current footprints are EAGLE-imports anyway and have other issues so it would be good to replace them.
Breaking DTACK out onto J3 is not correct - DTACK is always driven by IC5 and should not be driven directly by IO devices.
Instead, the IODTACK (an input to IC5) line should be broken out to the expansion connector, as this is a tri-state line that devices can drive when they are selected and can be put into Hi-Z at all other times. IC5 takes care of using this line when appropriate (though there is a linked issue with the timing of this - See #27 for details).
As a workaround for r0 and r1 boards, it is suggested that a jumper is soldered from IC5 pin 9 to the unused pin 16 on J5.
Currently, if the timer tick is enabled, it will always toggle GPIOs (to flash the green LED). This limits the utility of the GPIO port and makes efficient low-level programming more difficult.
While one can disable the timer completely with bclr.b #5,MFP_IMRB
, this also disables updating of the uptime counters, and so is not optimal. There should be a variable in the SDB that one can set to disable the GPIO toggling, while still allowing the timer to continue operating.
On r0, r1 and r1.2 board the RUN LED is the wrong way around.
ACs:
Instead of just removing the memory hole mentioned in #32 and returning that address space to EXP, we should use the whole top megabyte for IO and ROM to allow more expansion options.
The current thinking is to map it 50/50 - 512KiB each for IO (0xF00000-0xF7FFFF) and ROM (0xF80000-0xFFFFFF).
Thanks to @rts4e75 for the suggestion on Discord.
Requires hardware changes (more address lines into the decoder) and probably a bigger GAL, tagging for r2.
The 1.2 (and up) firmware does not work on MC68000. This is due to the temporary bus error handler, which assumes a minimum of 68010 (and treats the stack frame accordingly).
For 68000, the easiest thing to do is just unstack the frame and jump directly (as it does not support software re-run).
As part of this fix, it's also worth bringing in the 68020 support from the development firmware.
Look into supporting in-circuit EEPROM reprogramming. Would entail:
This should be doable without too much trouble, and might be a use for the MFP (in conjunction with a bit of glue, this would probably fit in the existing GALs).
I use no FTDI cable but an RS232 to USB cable (PL2302). With this I have an issue that after loading a program via Kermit that no ready message is shown. This due an USB reset after Kermit did load the file.
As I insert a readchar call in kmain of ehbasic or adventure then I can get the start-up message of that particular program after pressing a key. This is a dirty hack. I think the delay after loading a program is to short. (So I read from the ROM sourcecode)
When addressing expansion space, the glue logic in IC5 does not correctly generate DTACK. This causes the computer to hang, and makes it impossible to support memory expansions at present.
In keeping with the zero-wait-state design of the onboard RAM and ROM, it seems reasonable to stipulate that memory expansions be fast enough to support zero-wait-state also - anything that doesn't should really be mapped into IO space rather than expansion (which is reserved purely for memory).
The fix is a small change in the CUPL code for IC5. DTACK generation is currently:
DTACK = ((IOSEL # IACK) & MFPDTACK) # (!IACK & EVENROMSEL) # (!IACK & ODDROMSEL) # (!IACK & EVENRAMSEL) # (!IACK & ODDRAMSEL);
This should be changed to:
DTACK = ((IOSEL # IACK) & MFPDTACK) # (!IACK & EVENROMSEL) # (!IACK & ODDROMSEL) # (!IACK & EVENRAMSEL) # (!IACK & ODDRAMSEL) # (!IACK & !ODDROMSEL & !EVENROMSEL & !ODDRAMSEL & !EVENRAMSEL & !IOSEL);
(This isn't particularly efficient, but does not require hardware changes. It might be worth revisiting this issue in a future board revision).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.